From afe00aa90f9ae6b8ee8acf07bf4ff0969c364108 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 1 Feb 2019 09:59:51 -0500 Subject: [PATCH 1/9] Borrow temporary queus and frames on Rust side --- examples/hello_triangle_rust/main.rs | 9 +++--- wgpu-native/src/swap_chain.rs | 10 +++--- wgpu-rs/src/lib.rs | 46 ++++++++++++++++------------ 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index ba6ed735c2..b1c800cc4a 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, }, @@ -68,7 +68,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 +95,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 +116,6 @@ fn main() { .get_queue() .submit(&[cmd_buf]); - swap_chain.present(); ControlFlow::Continue }); } 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..b2dc5b4e4b 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -4,6 +4,7 @@ extern crate wgpu_native as wgn; use arrayvec::ArrayVec; use std::ffi::CString; +use std::marker::PhantomData; use std::ops::Range; use std::ptr; @@ -112,8 +113,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> { @@ -155,6 +157,12 @@ pub struct RenderPassDescriptor<'a> { Option>, } +pub struct SwapChainOutput<'a> { + pub texture: Texture, + pub view: TextureView, + swap_chain_id: &'a wgn::SwapChainId, +} + impl Instance { pub fn new() -> Self { Instance { @@ -197,10 +205,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, } } @@ -476,8 +484,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 +494,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, + } } } From ed5499d025fa1b14c03aaeac527a7b3ad132f542 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 1 Feb 2019 10:00:17 -0500 Subject: [PATCH 2/9] Basic gfx-examples framework --- Cargo.lock | 10 ++++ Cargo.toml | 1 + gfx-examples/Cargo.toml | 25 ++++++++++ gfx-examples/README.md | 6 +++ gfx-examples/src/framework.rs | 89 +++++++++++++++++++++++++++++++++++ gfx-examples/src/triangle.rs | 22 +++++++++ 6 files changed, 153 insertions(+) create mode 100644 gfx-examples/Cargo.toml create mode 100644 gfx-examples/README.md create mode 100644 gfx-examples/src/framework.rs create mode 100644 gfx-examples/src/triangle.rs diff --git a/Cargo.lock b/Cargo.lock index 9b808d0234..2e8361e235 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -391,6 +391,16 @@ dependencies = [ "xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gfx-examples" +version = "0.1.0" +dependencies = [ + "env_logger 0.5.13 (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" 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/gfx-examples/Cargo.toml b/gfx-examples/Cargo.toml new file mode 100644 index 0000000000..e35bdc3ffa --- /dev/null +++ b/gfx-examples/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "gfx-examples" +version = "0.1.0" +authors = [ + "Dzmitry Malyshau ", + "Joshua Groves ", +] +publish = false + +[[bin]] +name = "triangle" +path = "src/triangle.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"] } +env_logger = "0.5" +log = "0.4" diff --git a/gfx-examples/README.md b/gfx-examples/README.md new file mode 100644 index 0000000000..6f4c307dd9 --- /dev/null +++ b/gfx-examples/README.md @@ -0,0 +1,6 @@ +# gfx pre-ll examples + +Original gfx-rs examples were growing for years, but then got abandoned once we changed the API to match vulkan: +https://github.com/gfx-rs/gfx/tree/pre-ll/examples + +This is the new home for them, considering `wgpu-rs` to be the spiritual successor of gfx pre-ll. diff --git a/gfx-examples/src/framework.rs b/gfx-examples/src/framework.rs new file mode 100644 index 0000000000..24fe6b9bf3 --- /dev/null +++ b/gfx-examples/src/framework.rs @@ -0,0 +1,89 @@ +extern crate env_logger; +extern crate log; +extern crate wgpu_native; + +pub use self::wgpu_native::winit; + +use self::log::info; + + +pub const SWAP_CHAIN_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::B8g8r8a8Unorm; + +pub trait Example { + fn init(device: &wgpu::Device) -> Self; + fn update(&mut self, event: winit::WindowEvent); + fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device); +} + +pub fn run() { + use self::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 device = adapter.create_device(&wgpu::DeviceDescriptor { + extensions: wgpu::Extensions { + anisotropic_filtering: false, + }, + }); + + info!("Initializing the example..."); + let mut example = E::init(&device); + + info!("Initializing the window..."); + let mut events_loop = EventsLoop::new(); + let window = Window::new(&events_loop).unwrap(); + let size = window + .get_inner_size() + .unwrap() + .to_physical(window.get_hidpi_factor()); + + let surface = instance.create_surface(&window); + let mut swap_chain = device.create_swap_chain(&surface, &wgpu::SwapChainDescriptor { + usage: wgpu::TextureUsageFlags::OUTPUT_ATTACHMENT, + format: SWAP_CHAIN_FORMAT, + width: size.width as u32, + height: size.height as u32, + }); + + 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, &device); + } +} diff --git a/gfx-examples/src/triangle.rs b/gfx-examples/src/triangle.rs new file mode 100644 index 0000000000..6adf60c5fa --- /dev/null +++ b/gfx-examples/src/triangle.rs @@ -0,0 +1,22 @@ +extern crate wgpu; + +#[path="framework.rs"] +mod fw; + +struct Triangle; + +impl fw::Example for Triangle { + fn init(device: &wgpu::Device) -> Self { + Triangle + } + + fn update(&mut self, _event: fw::winit::WindowEvent) { + } + + fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) { + } +} + +fn main() { + fw::run::(); +} From a735eddf812a33f1aad1e7e44bf941b403f81a73 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sat, 2 Feb 2019 22:37:51 -0500 Subject: [PATCH 3/9] Sampler creation support --- wgpu-bindings/wgpu.h | 36 +++++++++++++++++++++++++++++ wgpu-native/src/conv.rs | 24 +++++++++++++++++++- wgpu-native/src/device.rs | 45 ++++++++++++++++++++++++++++++++++++- wgpu-native/src/resource.rs | 2 +- wgpu-rs/src/lib.rs | 10 ++++++++- 5 files changed, 113 insertions(+), 4 deletions(-) diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index 8435b4c841..12cc9eec4d 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,11 @@ typedef enum { WGPUCompareFunction_Always = 7, } WGPUCompareFunction; +typedef enum { + WGPUFilterMode_Nearest = 0, + WGPUFilterMode_Linear = 1, +} WGPUFilterMode; + typedef enum { WGPULoadOp_Clear = 0, WGPULoadOp_Load = 1, @@ -317,6 +335,20 @@ typedef struct { WGPUDepthStencilStateId depth_stencil_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; @@ -444,6 +476,8 @@ typedef struct { #define WGPUTextureUsageFlags_TRANSFER_SRC 1 +#define WGPUTextureUsageFlags_UNINITIALIZED 65535 + #define WGPUTrackPermit_EXTEND (WGPUTrackPermit){ .bits = 1 } #define WGPUTrackPermit_REPLACE (WGPUTrackPermit){ .bits = 2 } @@ -498,6 +532,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); diff --git a/wgpu-native/src/conv.rs b/wgpu-native/src/conv.rs index 4e9c02e87c..be48535d7d 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -1,4 +1,5 @@ use crate::{binding_model, command, pipeline, resource, Color, Extent3d}; +use log::warn; pub fn map_buffer_usage( usage: resource::BufferUsageFlags, @@ -222,7 +223,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 { @@ -408,3 +409,24 @@ 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 => { + warn!("MirrorRepeat isn't supported yet"); + W::Tile + } + Am::ClampToBorderColor => W::Border, + } +} \ No newline at end of file diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index e187c3356c..b327daae7a 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, 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-rs/src/lib.rs b/wgpu-rs/src/lib.rs index b2dc5b4e4b..2733996bdd 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -10,11 +10,13 @@ use std::ptr; pub use wgn::{ AdapterDescriptor, Attachment, BindGroupLayoutBinding, BindingType, BlendStateDescriptor, - BufferDescriptor, Color, ColorWriteFlags, CommandBufferDescriptor, DepthStencilStateDescriptor, + BufferDescriptor, BufferUsageFlags, + 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 { @@ -353,6 +355,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), From d4c8c881d07c7a291d5b08194d455556615ee3c7 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sat, 2 Feb 2019 22:39:13 -0500 Subject: [PATCH 4/9] gfx framework GLSL reading, most of the cube example --- Cargo.lock | 85 ++++++++++++ gfx-examples/Cargo.toml | 5 +- gfx-examples/data/cube.frag | 13 ++ gfx-examples/data/cube.vert | 15 +++ gfx-examples/src/cube.rs | 238 ++++++++++++++++++++++++++++++++++ gfx-examples/src/framework.rs | 30 ++++- gfx-examples/src/triangle.rs | 22 ---- wgpu-native/src/instance.rs | 35 +++-- 8 files changed, 404 insertions(+), 39 deletions(-) create mode 100644 gfx-examples/data/cube.frag create mode 100644 gfx-examples/data/cube.vert create mode 100644 gfx-examples/src/cube.rs delete mode 100644 gfx-examples/src/triangle.rs diff --git a/Cargo.lock b/Cargo.lock index 2e8361e235..b2e03a5318 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" @@ -157,6 +176,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 +242,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 +304,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 +349,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" @@ -396,6 +444,7 @@ name = "gfx-examples" version = "0.1.0" dependencies = [ "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", @@ -411,6 +460,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" @@ -912,6 +971,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" @@ -1066,6 +1136,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" @@ -1310,6 +1385,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" @@ -1318,35 +1394,42 @@ 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 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" @@ -1408,6 +1491,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" @@ -1425,6 +1509,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/gfx-examples/Cargo.toml b/gfx-examples/Cargo.toml index e35bdc3ffa..7bb2cfb86b 100644 --- a/gfx-examples/Cargo.toml +++ b/gfx-examples/Cargo.toml @@ -8,8 +8,8 @@ authors = [ publish = false [[bin]] -name = "triangle" -path = "src/triangle.rs" +name = "cube" +path = "src/cube.rs" [features] default = [] @@ -22,4 +22,5 @@ vulkan = ["wgpu-native/gfx-backend-vulkan"] wgpu-native = { path = "../wgpu-native" } wgpu = { path = "../wgpu-rs", features = ["winit"] } env_logger = "0.5" +glsl-to-spirv = "0.1" log = "0.4" diff --git a/gfx-examples/data/cube.frag b/gfx-examples/data/cube.frag new file mode 100644 index 0000000000..64bfb9d605 --- /dev/null +++ b/gfx-examples/data/cube.frag @@ -0,0 +1,13 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec2 v_TexCoord; +layout(location = 0) out vec4 o_Target; +layout(set = 0, binding = 0) uniform texture2D t_Color; +layout(set = 0, binding = 1) uniform sampler s_Color; + +void main() { + vec4 tex = texture(sampler2D(t_Color, s_Color), v_TexCoord); + float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5)); + o_Target = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0); +} diff --git a/gfx-examples/data/cube.vert b/gfx-examples/data/cube.vert new file mode 100644 index 0000000000..18838a4ca5 --- /dev/null +++ b/gfx-examples/data/cube.vert @@ -0,0 +1,15 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +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..d92a792b95 --- /dev/null +++ b/gfx-examples/src/cube.rs @@ -0,0 +1,238 @@ +extern crate wgpu; + +#[path="framework.rs"] +mod fw; + + +#[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()) +} + +struct Cube { + vertex_buf: wgpu::Buffer, + index_buf: wgpu::Buffer, + bind_group: wgpu::BindGroup, + pipeline: wgpu::RenderPipeline, +} + +impl fw::Example for Cube { + fn init(device: &mut wgpu::Device) -> 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, unsafe { mem::transmute(&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, unsafe { mem::transmute(&index_data[..]) }); + + // Create pipeline layout + let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + bindings: &[ + wgpu::BindGroupLayoutBinding { + binding: 0, + visibility: wgpu::ShaderStageFlags::FRAGMENT, + ty: wgpu::BindingType::SampledTexture, + }, + wgpu::BindGroupLayoutBinding { + binding: 1, + 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 texels = [0x20u8, 0xA0, 0xC0, 0xFF]; + let texture = device.create_texture(&wgpu::TextureDescriptor { + size: wgpu::Extent3d { + width: 1, + height: 1, + depth: 1, + }, + 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(); //TODO! + + // Create the bind group + 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::Nearest, + 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 bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &bind_group_layout, + bindings: &[ + wgpu::Binding { + binding: 0, + resource: wgpu::BindingResource::TextureView(&texture_view), + }, + wgpu::Binding { + binding: 1, + resource: wgpu::BindingResource::Sampler(&sampler), + }, + ], + }); + + // Create the render pipeline + let (vs_bytes, fs_bytes) = fw::load_glsl_pair("cube"); + 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: fw::SWAP_CHAIN_FORMAT, + samples: 1, + }], + depth_stencil_attachment: None, + }, + blend_states: &[&blend_state0], + depth_stencil_state: &depth_stencil_state, + }); + + // Done + device.get_queue().submit(&[init_command_buf]); + Cube { + vertex_buf, + index_buf, + bind_group, + pipeline, + } + } + + fn update(&mut self, _event: fw::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::GREEN, + }], + depth_stencil_attachment: None, + }); + rpass.set_pipeline(&self.pipeline); + //rpass.bind_groups(); + //rpass.set_vertex_buffers(); + rpass.draw(0..3, 0..1); + rpass.end_pass(); + } + + device + .get_queue() + .submit(&[cmd_buf]); + } +} + +fn main() { + fw::run::(); +} diff --git a/gfx-examples/src/framework.rs b/gfx-examples/src/framework.rs index 24fe6b9bf3..ce019ca7d0 100644 --- a/gfx-examples/src/framework.rs +++ b/gfx-examples/src/framework.rs @@ -1,4 +1,5 @@ extern crate env_logger; +extern crate glsl_to_spirv; extern crate log; extern crate wgpu_native; @@ -9,10 +10,29 @@ use self::log::info; pub const SWAP_CHAIN_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::B8g8r8a8Unorm; +pub fn load_glsl_pair(name: &str) -> (Vec, Vec) { + use self::glsl_to_spirv::{ShaderType, compile}; + use std::fs::read_to_string; + use std::io::Read; + use std::path::PathBuf; + + let base_path = PathBuf::from("data").join(name); + let code_vs = read_to_string(base_path.with_extension("vert")).unwrap(); + let code_fs = read_to_string(base_path.with_extension("frag")).unwrap(); + + let mut output_vs = compile(&code_vs, ShaderType::Vertex).unwrap(); + let mut output_fs = compile(&code_fs, ShaderType::Fragment).unwrap(); + + let (mut spv_vs, mut spv_fs) = (Vec::new(), Vec::new()); + output_vs.read_to_end(&mut spv_vs).unwrap(); + output_fs.read_to_end(&mut spv_fs).unwrap(); + (spv_vs, spv_fs) +} + pub trait Example { - fn init(device: &wgpu::Device) -> Self; + fn init(device: &mut wgpu::Device) -> Self; fn update(&mut self, event: winit::WindowEvent); - fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device); + fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device); } pub fn run() { @@ -26,14 +46,14 @@ pub fn run() { 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, }, }); info!("Initializing the example..."); - let mut example = E::init(&device); + let mut example = E::init(&mut device); info!("Initializing the window..."); let mut events_loop = EventsLoop::new(); @@ -84,6 +104,6 @@ pub fn run() { }); let frame = swap_chain.get_next_texture(); - example.render(&frame, &device); + example.render(&frame, &mut device); } } diff --git a/gfx-examples/src/triangle.rs b/gfx-examples/src/triangle.rs deleted file mode 100644 index 6adf60c5fa..0000000000 --- a/gfx-examples/src/triangle.rs +++ /dev/null @@ -1,22 +0,0 @@ -extern crate wgpu; - -#[path="framework.rs"] -mod fw; - -struct Triangle; - -impl fw::Example for Triangle { - fn init(device: &wgpu::Device) -> Self { - Triangle - } - - fn update(&mut self, _event: fw::winit::WindowEvent) { - } - - fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) { - } -} - -fn main() { - fw::run::(); -} diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 79f7ad1a6b..b8ec8655d9 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -50,17 +50,32 @@ 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, - }; + #[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)] From 3d47436129e3e7a9caf3753415ac2c8cacd5bd01 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sun, 3 Feb 2019 15:51:54 -0500 Subject: [PATCH 5/9] rust: vertex/index binding --- gfx-examples/src/cube.rs | 5 +++-- wgpu-native/src/command/render.rs | 14 +++++++++++--- wgpu-native/src/instance.rs | 1 + wgpu-rs/src/lib.rs | 19 +++++++++++++++++++ 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/gfx-examples/src/cube.rs b/gfx-examples/src/cube.rs index d92a792b95..92be14edb5 100644 --- a/gfx-examples/src/cube.rs +++ b/gfx-examples/src/cube.rs @@ -221,8 +221,9 @@ impl fw::Example for Cube { depth_stencil_attachment: None, }); rpass.set_pipeline(&self.pipeline); - //rpass.bind_groups(); - //rpass.set_vertex_buffers(); + 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(0..3, 0..1); rpass.end_pass(); } 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/instance.rs b/wgpu-native/src/instance.rs index b8ec8655d9..a66161ed15 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -50,6 +50,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_winit( instance_id: InstanceId, window: &winit::Window, ) -> SurfaceId { + //TODO: remove these workarounds when porting on gfx-hal 0.2 #[cfg(any( feature = "gfx-backend-vulkan", feature = "gfx-backend-dx11", diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index 2733996bdd..ffa8b61c2b 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -451,6 +451,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, From 3ec4ff99b05027e47d17a7675c9f007a9e26c2b8 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sun, 3 Feb 2019 20:39:08 -0500 Subject: [PATCH 6/9] Vertex buffer description in the pipelines --- examples/hello_triangle_rust/main.rs | 2 ++ gfx-examples/data/cube.frag | 4 +-- gfx-examples/src/cube.rs | 23 +++++++++++++-- wgpu-bindings/wgpu.h | 44 ++++++++++++++++++++++++++++ wgpu-native/src/conv.rs | 13 +++++++- wgpu-native/src/device.rs | 36 +++++++++++++++++++---- wgpu-native/src/pipeline.rs | 21 +++++++------ wgpu-rs/src/lib.rs | 23 +++++++++++++++ 8 files changed, 145 insertions(+), 21 deletions(-) diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index b1c800cc4a..9120a4b0b6 100644 --- a/examples/hello_triangle_rust/main.rs +++ b/examples/hello_triangle_rust/main.rs @@ -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")] diff --git a/gfx-examples/data/cube.frag b/gfx-examples/data/cube.frag index 64bfb9d605..826ebf4368 100644 --- a/gfx-examples/data/cube.frag +++ b/gfx-examples/data/cube.frag @@ -3,8 +3,8 @@ layout(location = 0) in vec2 v_TexCoord; layout(location = 0) out vec4 o_Target; -layout(set = 0, binding = 0) uniform texture2D t_Color; -layout(set = 0, binding = 1) uniform sampler s_Color; +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); diff --git a/gfx-examples/src/cube.rs b/gfx-examples/src/cube.rs index 92be14edb5..61dd63ba97 100644 --- a/gfx-examples/src/cube.rs +++ b/gfx-examples/src/cube.rs @@ -96,12 +96,12 @@ impl fw::Example for Cube { let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { bindings: &[ wgpu::BindGroupLayoutBinding { - binding: 0, + binding: 1, visibility: wgpu::ShaderStageFlags::FRAGMENT, ty: wgpu::BindingType::SampledTexture, }, wgpu::BindGroupLayoutBinding { - binding: 1, + binding: 2, visibility: wgpu::ShaderStageFlags::FRAGMENT, ty: wgpu::BindingType::Sampler, }, @@ -193,6 +193,25 @@ impl fw::Example for Cube { }, 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 diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index 12cc9eec4d..94cf5ccb30 100644 --- a/wgpu-bindings/wgpu.h +++ b/wgpu-bindings/wgpu.h @@ -69,6 +69,16 @@ typedef enum { 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, @@ -131,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; @@ -324,6 +341,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; @@ -333,6 +371,7 @@ typedef struct { const WGPUBlendStateId *blend_states; uintptr_t blend_states_length; WGPUDepthStencilStateId depth_stencil_state; + WGPUVertexBufferStateDescriptor vertex_buffer_state; } WGPURenderPipelineDescriptor; typedef struct { @@ -588,6 +627,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/conv.rs b/wgpu-native/src/conv.rs index be48535d7d..0ce936f19b 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -264,6 +264,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 @@ -429,4 +440,4 @@ pub fn map_wrap(address: resource::AddressMode) -> hal::image::WrapMode { } Am::ClampToBorderColor => W::Border, } -} \ No newline at end of file +} diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index b327daae7a..42f495982e 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -1044,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 = Vec::with_capacity(desc_vbs.len()); + let mut attributes: Vec = 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/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-rs/src/lib.rs b/wgpu-rs/src/lib.rs index ffa8b61c2b..1acf7be00c 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -11,6 +11,7 @@ use std::ptr; pub use wgn::{ AdapterDescriptor, Attachment, BindGroupLayoutBinding, BindingType, BlendStateDescriptor, BufferDescriptor, BufferUsageFlags, + IndexFormat, VertexFormat, InputStepMode, ShaderAttributeIndex, VertexAttributeDescriptor, Color, ColorWriteFlags, CommandBufferDescriptor, DepthStencilStateDescriptor, DeviceDescriptor, Extensions, Extent3d, LoadOp, Origin3d, PowerPreference, PrimitiveTopology, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, @@ -144,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>], @@ -151,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> { @@ -316,6 +325,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( @@ -338,6 +356,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(), + }, }, ), } From d50f8199ddf0ef824d1496a644f445599fe72721 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sun, 3 Feb 2019 21:59:35 -0500 Subject: [PATCH 7/9] Buffer to texture copies --- Cargo.lock | 12 +++++ gfx-examples/Cargo.toml | 1 + gfx-examples/src/cube.rs | 70 ++++++++++++++++++++---- gfx-examples/src/framework.rs | 9 ++++ wgpu-bindings/wgpu.h | 41 +++++++++++--- wgpu-native/src/command/mod.rs | 98 +++++++++++++++++++++++++++++++++- wgpu-native/src/conv.rs | 22 +++++++- wgpu-rs/src/lib.rs | 51 ++++++++++++++++++ 8 files changed, 283 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2e03a5318..e74bdb3695 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,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" @@ -443,6 +453,7 @@ dependencies = [ 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)", @@ -1400,6 +1411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "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" diff --git a/gfx-examples/Cargo.toml b/gfx-examples/Cargo.toml index 7bb2cfb86b..41af92cce0 100644 --- a/gfx-examples/Cargo.toml +++ b/gfx-examples/Cargo.toml @@ -21,6 +21,7 @@ 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/src/cube.rs b/gfx-examples/src/cube.rs index 61dd63ba97..f1bd1c3228 100644 --- a/gfx-examples/src/cube.rs +++ b/gfx-examples/src/cube.rs @@ -1,3 +1,4 @@ +extern crate cgmath; extern crate wgpu; #[path="framework.rs"] @@ -85,16 +86,21 @@ impl fw::Example for Cube { size: (vertex_data.len() * vertex_size) as u32, usage: wgpu::BufferUsageFlags::VERTEX | wgpu::BufferUsageFlags::TRANSFER_DST, }); - vertex_buf.set_sub_data(0, unsafe { mem::transmute(&vertex_data[..]) }); + vertex_buf.set_sub_data(0, fw::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, unsafe { mem::transmute(&index_data[..]) }); + index_buf.set_sub_data(0, fw::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, @@ -113,12 +119,13 @@ impl fw::Example for Cube { // Create the texture let texels = [0x20u8, 0xA0, 0xC0, 0xFF]; + let texture_extent = wgpu::Extent3d { + width: 1, + height: 1, + depth: 1, + }; let texture = device.create_texture(&wgpu::TextureDescriptor { - size: wgpu::Extent3d { - width: 1, - height: 1, - depth: 1, - }, + size: texture_extent, array_size: 1, dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::R8g8b8a8Unorm, @@ -130,9 +137,27 @@ impl fw::Example for Cube { usage: wgpu::BufferUsageFlags::TRANSFER_SRC | wgpu::BufferUsageFlags::TRANSFER_DST }); temp_buf.set_sub_data(0, &texels); - //init_command_buf.copy_buffer_to_texture(); //TODO! + init_command_buf.copy_buffer_to_texture( + wgpu::BufferCopyView { + buffer: &temp_buf, + offset: 0, + row_pitch: 4, + image_height: 1, + }, + wgpu::TextureCopyView { + texture: &texture, + level: 0, + slice: 0, + origin: wgpu::Origin3d { + x: 0.0, + y: 0.0, + z: 0.0, + }, + }, + texture_extent, + ); - // Create the bind group + // Create other resources let sampler = device.create_sampler(&wgpu::SamplerDescriptor { r_address_mode: wgpu::AddressMode::ClampToEdge, s_address_mode: wgpu::AddressMode::ClampToEdge, @@ -146,15 +171,40 @@ impl fw::Example for Cube { 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 = 1.0; //TODO + 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(); + vertex_buf.set_sub_data(0, fw::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::TextureView(&texture_view), + 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), }, ], diff --git a/gfx-examples/src/framework.rs b/gfx-examples/src/framework.rs index ce019ca7d0..cdceac1750 100644 --- a/gfx-examples/src/framework.rs +++ b/gfx-examples/src/framework.rs @@ -10,6 +10,15 @@ use self::log::info; pub const SWAP_CHAIN_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::B8g8r8a8Unorm; +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_pair(name: &str) -> (Vec, Vec) { use self::glsl_to_spirv::{ShaderType, compile}; use std::fs::read_to_string; diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index 94cf5ccb30..1962351485 100644 --- a/wgpu-bindings/wgpu.h +++ b/wgpu-bindings/wgpu.h @@ -200,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; @@ -410,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; @@ -536,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); diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 61e36b71ca..427a19c4c2 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, }; @@ -379,3 +380,96 @@ 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 / 8; + 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/conv.rs b/wgpu-native/src/conv.rs index 0ce936f19b..096454afb1 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -1,6 +1,10 @@ -use crate::{binding_model, command, pipeline, resource, Color, Extent3d}; +use crate::{ + binding_model, command, pipeline, resource, Color, + Extent3d, Origin3d, +}; use log::warn; + pub fn map_buffer_usage( usage: resource::BufferUsageFlags, ) -> (hal::buffer::Usage, hal::memory::Properties) { @@ -101,6 +105,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::*; diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index 1acf7be00c..4b222569a4 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -174,6 +174,43 @@ pub struct SwapChainOutput<'a> { 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 { @@ -458,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> { From 8f985dd09e336bf6a846e532b04466df1491dd37 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Sun, 3 Feb 2019 22:19:36 -0500 Subject: [PATCH 8/9] Fix gfx-cube example --- gfx-examples/src/cube.rs | 8 +++++--- gfx-examples/src/framework.rs | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/gfx-examples/src/cube.rs b/gfx-examples/src/cube.rs index f1bd1c3228..4fb56c911d 100644 --- a/gfx-examples/src/cube.rs +++ b/gfx-examples/src/cube.rs @@ -67,6 +67,7 @@ fn create_vertices() -> (Vec, Vec) { struct Cube { vertex_buf: wgpu::Buffer, index_buf: wgpu::Buffer, + index_count: usize, bind_group: wgpu::BindGroup, pipeline: wgpu::RenderPipeline, } @@ -185,7 +186,7 @@ impl fw::Example for Cube { ); let mx_total = mx_projection * mx_view; let mx_raw: &[f32; 16] = mx_total.as_ref(); - vertex_buf.set_sub_data(0, fw::cast_slice(&mx_raw[..])); + uniform_buf.set_sub_data(0, fw::cast_slice(&mx_raw[..])); } // Create bind group @@ -269,6 +270,7 @@ impl fw::Example for Cube { Cube { vertex_buf, index_buf, + index_count: index_data.len(), bind_group, pipeline, } @@ -293,7 +295,7 @@ impl fw::Example for Cube { 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(0..3, 0..1); + rpass.draw_indexed(0 .. self.index_count as u32, 0, 0..1); rpass.end_pass(); } @@ -304,5 +306,5 @@ impl fw::Example for Cube { } fn main() { - fw::run::(); + fw::run::("cube"); } diff --git a/gfx-examples/src/framework.rs b/gfx-examples/src/framework.rs index cdceac1750..08727e496b 100644 --- a/gfx-examples/src/framework.rs +++ b/gfx-examples/src/framework.rs @@ -44,7 +44,7 @@ pub trait Example { fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device); } -pub fn run() { +pub fn run(title: &str) { use self::wgpu_native::winit::{ Event, ElementState, EventsLoop, KeyboardInput, Window, WindowEvent, VirtualKeyCode }; @@ -67,6 +67,7 @@ pub fn run() { 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() From c74f8e8db8b3a9ad314f94a786acab51e714d1f4 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 4 Feb 2019 09:55:32 -0500 Subject: [PATCH 9/9] Cube cleanup and the new generated texture --- gfx-examples/Cargo.toml | 1 + gfx-examples/README.md | 4 +-- gfx-examples/data/cube.frag | 5 ++- gfx-examples/data/cube.vert | 1 - gfx-examples/src/cube.rs | 65 ++++++++++++++++++++++------------ gfx-examples/src/framework.rs | 53 ++++++++++++--------------- wgpu-native/src/command/mod.rs | 5 ++- wgpu-native/src/conv.rs | 6 +--- wgpu-native/src/device.rs | 4 +-- 9 files changed, 78 insertions(+), 66 deletions(-) diff --git a/gfx-examples/Cargo.toml b/gfx-examples/Cargo.toml index 41af92cce0..7e3ae1ade3 100644 --- a/gfx-examples/Cargo.toml +++ b/gfx-examples/Cargo.toml @@ -5,6 +5,7 @@ authors = [ "Dzmitry Malyshau ", "Joshua Groves ", ] +edition = "2018" publish = false [[bin]] diff --git a/gfx-examples/README.md b/gfx-examples/README.md index 6f4c307dd9..318957ad0a 100644 --- a/gfx-examples/README.md +++ b/gfx-examples/README.md @@ -1,6 +1,6 @@ # gfx pre-ll examples -Original gfx-rs examples were growing for years, but then got abandoned once we changed the API to match vulkan: +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 -This is the new home for them, considering `wgpu-rs` to be the spiritual successor of gfx pre-ll. +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 index 826ebf4368..b88e3abf0c 100644 --- a/gfx-examples/data/cube.frag +++ b/gfx-examples/data/cube.frag @@ -1,5 +1,4 @@ #version 450 -#extension GL_ARB_separate_shader_objects : enable layout(location = 0) in vec2 v_TexCoord; layout(location = 0) out vec4 o_Target; @@ -8,6 +7,6 @@ layout(set = 0, binding = 2) uniform sampler s_Color; void main() { vec4 tex = texture(sampler2D(t_Color, s_Color), v_TexCoord); - float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5)); - o_Target = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0); + 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 index 18838a4ca5..6a4028e7a1 100644 --- a/gfx-examples/data/cube.vert +++ b/gfx-examples/data/cube.vert @@ -1,5 +1,4 @@ #version 450 -#extension GL_ARB_separate_shader_objects : enable layout(location = 0) in vec4 a_Pos; layout(location = 1) in vec2 a_TexCoord; diff --git a/gfx-examples/src/cube.rs b/gfx-examples/src/cube.rs index 4fb56c911d..1a9a4a2198 100644 --- a/gfx-examples/src/cube.rs +++ b/gfx-examples/src/cube.rs @@ -1,8 +1,4 @@ -extern crate cgmath; -extern crate wgpu; - -#[path="framework.rs"] -mod fw; +mod framework; #[derive(Clone)] @@ -64,6 +60,29 @@ fn create_vertices() -> (Vec, Vec) { (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, @@ -72,8 +91,8 @@ struct Cube { pipeline: wgpu::RenderPipeline, } -impl fw::Example for Cube { - fn init(device: &mut wgpu::Device) -> Self { +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 { @@ -87,12 +106,12 @@ impl fw::Example for Cube { size: (vertex_data.len() * vertex_size) as u32, usage: wgpu::BufferUsageFlags::VERTEX | wgpu::BufferUsageFlags::TRANSFER_DST, }); - vertex_buf.set_sub_data(0, fw::cast_slice(&vertex_data)); + 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, fw::cast_slice(&index_data)); + 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 { @@ -119,10 +138,11 @@ impl fw::Example for Cube { }); // Create the texture - let texels = [0x20u8, 0xA0, 0xC0, 0xFF]; + let size = 256u32; + let texels = create_texels(size as usize); let texture_extent = wgpu::Extent3d { - width: 1, - height: 1, + width: size, + height: size, depth: 1, }; let texture = device.create_texture(&wgpu::TextureDescriptor { @@ -142,8 +162,8 @@ impl fw::Example for Cube { wgpu::BufferCopyView { buffer: &temp_buf, offset: 0, - row_pitch: 4, - image_height: 1, + row_pitch: 4 * size, + image_height: size, }, wgpu::TextureCopyView { texture: &texture, @@ -164,7 +184,7 @@ impl fw::Example for Cube { s_address_mode: wgpu::AddressMode::ClampToEdge, t_address_mode: wgpu::AddressMode::ClampToEdge, mag_filter: wgpu::FilterMode::Nearest, - min_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Linear, mipmap_filter: wgpu::FilterMode::Nearest, lod_min_clamp: -100.0, lod_max_clamp: 100.0, @@ -177,7 +197,7 @@ impl fw::Example for Cube { usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST, }); { - let aspect_ratio = 1.0; //TODO + 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), @@ -186,7 +206,7 @@ impl fw::Example for Cube { ); let mx_total = mx_projection * mx_view; let mx_raw: &[f32; 16] = mx_total.as_ref(); - uniform_buf.set_sub_data(0, fw::cast_slice(&mx_raw[..])); + uniform_buf.set_sub_data(0, framework::cast_slice(&mx_raw[..])); } // Create bind group @@ -212,7 +232,8 @@ impl fw::Example for Cube { }); // Create the render pipeline - let (vs_bytes, fs_bytes) = fw::load_glsl_pair("cube"); + 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); @@ -237,7 +258,7 @@ impl fw::Example for Cube { primitive_topology: wgpu::PrimitiveTopology::TriangleList, attachments_state: wgpu::AttachmentsState { color_attachments: &[wgpu::Attachment { - format: fw::SWAP_CHAIN_FORMAT, + format: sc_desc.format, samples: 1, }], depth_stencil_attachment: None, @@ -276,7 +297,7 @@ impl fw::Example for Cube { } } - fn update(&mut self, _event: fw::winit::WindowEvent) { + fn update(&mut self, _event: framework::winit::WindowEvent) { } fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) { @@ -287,7 +308,7 @@ impl fw::Example for Cube { attachment: &frame.view, load_op: wgpu::LoadOp::Clear, store_op: wgpu::StoreOp::Store, - clear_color: wgpu::Color::GREEN, + clear_color: wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }, }], depth_stencil_attachment: None, }); @@ -306,5 +327,5 @@ impl fw::Example for Cube { } fn main() { - fw::run::("cube"); + framework::run::("cube"); } diff --git a/gfx-examples/src/framework.rs b/gfx-examples/src/framework.rs index 08727e496b..77918c96c4 100644 --- a/gfx-examples/src/framework.rs +++ b/gfx-examples/src/framework.rs @@ -1,14 +1,7 @@ -extern crate env_logger; -extern crate glsl_to_spirv; -extern crate log; -extern crate wgpu_native; +pub use wgpu_native::winit; -pub use self::wgpu_native::winit; +use log::info; -use self::log::info; - - -pub const SWAP_CHAIN_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::B8g8r8a8Unorm; pub fn cast_slice(data: &[T]) -> &[u8] { use std::mem::size_of; @@ -19,33 +12,32 @@ pub fn cast_slice(data: &[T]) -> &[u8] { } } -pub fn load_glsl_pair(name: &str) -> (Vec, Vec) { - use self::glsl_to_spirv::{ShaderType, compile}; +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 base_path = PathBuf::from("data").join(name); - let code_vs = read_to_string(base_path.with_extension("vert")).unwrap(); - let code_fs = read_to_string(base_path.with_extension("frag")).unwrap(); - - let mut output_vs = compile(&code_vs, ShaderType::Vertex).unwrap(); - let mut output_fs = compile(&code_fs, ShaderType::Fragment).unwrap(); - - let (mut spv_vs, mut spv_fs) = (Vec::new(), Vec::new()); - output_vs.read_to_end(&mut spv_vs).unwrap(); - output_fs.read_to_end(&mut spv_fs).unwrap(); - (spv_vs, spv_fs) + 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) -> Self; + 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 self::wgpu_native::winit::{ + use wgpu_native::winit::{ Event, ElementState, EventsLoop, KeyboardInput, Window, WindowEvent, VirtualKeyCode }; @@ -61,9 +53,6 @@ pub fn run(title: &str) { }, }); - info!("Initializing the example..."); - let mut example = E::init(&mut device); - info!("Initializing the window..."); let mut events_loop = EventsLoop::new(); let window = Window::new(&events_loop).unwrap(); @@ -74,12 +63,16 @@ pub fn run(title: &str) { .to_physical(window.get_hidpi_factor()); let surface = instance.create_surface(&window); - let mut swap_chain = device.create_swap_chain(&surface, &wgpu::SwapChainDescriptor { + let sc_desc = wgpu::SwapChainDescriptor { usage: wgpu::TextureUsageFlags::OUTPUT_ATTACHMENT, - format: SWAP_CHAIN_FORMAT, + 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; diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 427a19c4c2..f897991262 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -34,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 { @@ -443,7 +445,8 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture( }); } - let bytes_per_texel = conv::map_texture_format(dst_texture.format).surface_desc().bits as u32 / 8; + 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 { diff --git a/wgpu-native/src/conv.rs b/wgpu-native/src/conv.rs index 096454afb1..41fff1e5a1 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -2,7 +2,6 @@ use crate::{ binding_model, command, pipeline, resource, Color, Extent3d, Origin3d, }; -use log::warn; pub fn map_buffer_usage( @@ -454,10 +453,7 @@ pub fn map_wrap(address: resource::AddressMode) -> hal::image::WrapMode { match address { Am::ClampToEdge => W::Clamp, Am::Repeat => W::Tile, - Am::MirrorRepeat => { - warn!("MirrorRepeat isn't supported yet"); - 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 42f495982e..aed76415ea 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -1047,8 +1047,8 @@ pub extern "C" fn wgpu_device_create_render_pipeline( 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 = Vec::with_capacity(desc_vbs.len()); - let mut attributes: Vec = Vec::new(); + 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