diff --git a/Cargo.lock b/Cargo.lock index bfb3cbad4f..f69be6f910 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1047,6 +1047,7 @@ dependencies = [ "gfx-backend-vulkan 0.1.0 (git+https://github.com/gfx-rs/gfx)", "gfx-hal 0.1.0 (git+https://github.com/gfx-rs/gfx.git)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rendy-memory 0.1.0 (git+https://github.com/rustgd/rendy?rev=ce7dd7f)", ] diff --git a/examples/hello_triangle_c/main.c b/examples/hello_triangle_c/main.c index 1765fdcf69..bcc7c475e8 100644 --- a/examples/hello_triangle_c/main.c +++ b/examples/hello_triangle_c/main.c @@ -122,8 +122,8 @@ int main() .stages = stages, .stages_length = STAGES_LENGTH, .primitive_topology = WGPUPrimitiveTopology_TriangleList, - .blend_state = blend_state, - .blend_state_length = BLEND_STATE_LENGTH, + .blend_states = blend_state, + .blend_states_length = BLEND_STATE_LENGTH, .depth_stencil_state = depth_stencil_state, .attachment_state = attachment_state, }; diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index 0a7fa35531..5cd9d225ce 100644 --- a/examples/hello_triangle_rust/main.rs +++ b/examples/hello_triangle_rust/main.rs @@ -10,6 +10,19 @@ fn main() { }, }); + let texture = device.create_texture(&wgpu::TextureDescriptor { + size: wgpu::Extent3d { + width: 256, + height: 256, + depth: 1, + }, + array_size: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::R8g8b8a8Unorm, + usage: wgpu::TextureUsageFlags::OUTPUT_ATTACHMENT, + }); + let color_view = texture.create_default_texture_view(); + let vs_bytes = include_bytes!("./../data/hello_triangle.vert.spv"); let vs_module = device.create_shader_module(vs_bytes); let fs_bytes = include_bytes!("./../data/hello_triangle.frag.spv"); @@ -43,7 +56,7 @@ fn main() { }, ], primitive_topology: wgpu::PrimitiveTopology::TriangleList, - blend_state: &[ + blend_states: &[ &blend_state0, ], depth_stencil_state: &depth_stencil_state, @@ -53,7 +66,6 @@ fn main() { let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor {}); { - let color_view = unimplemented!(); //TODO! let rpass = cmd_buf.begin_render_pass(&wgpu::RenderPassDescriptor { color_attachments: &[ wgpu::RenderPassColorAttachmentDescriptor { diff --git a/examples/vk_layer_settings.txt b/examples/vk_layer_settings.txt new file mode 100644 index 0000000000..2b3a1124d4 --- /dev/null +++ b/examples/vk_layer_settings.txt @@ -0,0 +1,19 @@ +lunarg_core_validation.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG +lunarg_core_validation.report_flags = error,warn,perf +lunarg_core_validation.log_filename = stdout + +lunarg_object_tracker.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG +lunarg_object_tracker.report_flags = error,warn,perf +lunarg_object_tracker.log_filename = stdout + +lunarg_parameter_validation.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG +lunarg_parameter_validation.report_flags = error,warn,perf +lunarg_parameter_validation.log_filename = stdout + +google_threading.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG +google_threading.report_flags = error,warn,perf +google_threading.log_filename = stdout + +google_unique_objects.debug_action = VK_DBG_LAYER_ACTION_LOG_MSG +google_unique_objects.report_flags = error,warn,perf +google_unique_objects.log_filename = stdout diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index bfa5e1530d..ea7bfffe48 100644 --- a/wgpu-bindings/wgpu.h +++ b/wgpu-bindings/wgpu.h @@ -219,8 +219,8 @@ typedef struct { const WGPUPipelineStageDescriptor *stages; uintptr_t stages_length; WGPUPrimitiveTopology primitive_topology; - const WGPUBlendStateId *blend_state; - uintptr_t blend_state_length; + const WGPUBlendStateId *blend_states; + uintptr_t blend_states_length; WGPUDepthStencilStateId depth_stencil_state; WGPUAttachmentStateId attachment_state; } WGPURenderPipelineDescriptor; @@ -304,7 +304,7 @@ WGPUDeviceId wgpu_adapter_create_device(WGPUAdapterId adapter_id, WGPUComputePassId wgpu_command_buffer_begin_compute_pass(WGPUCommandBufferId command_buffer_id); WGPURenderPassId wgpu_command_buffer_begin_render_pass(WGPUCommandBufferId command_buffer_id, - WGPURenderPassDescriptor_WGPUTextureViewId _descriptor); + WGPURenderPassDescriptor_WGPUTextureViewId desc); WGPUCommandBufferId wgpu_compute_pass_end_pass(WGPUComputePassId pass_id); diff --git a/wgpu-native/Cargo.toml b/wgpu-native/Cargo.toml index 40d5c911d9..294c2b8dcb 100644 --- a/wgpu-native/Cargo.toml +++ b/wgpu-native/Cargo.toml @@ -16,6 +16,7 @@ remote = ["parking_lot"] [dependencies] bitflags = "1.0" lazy_static = "1.1.0" +log = "0.4" parking_lot = { version = "0.6", optional = true } gfx-hal = { git = "https://github.com/gfx-rs/gfx" } # required by gfx-memory gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx" } diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 14bdbcf897..c8cd8077c0 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -6,15 +6,19 @@ pub use self::allocator::CommandAllocator; pub use self::compute::*; pub use self::render::*; -use hal; +use hal::{self, Device}; +use hal::command::RawCommandBuffer; use { - Color, Origin3d, Stored, + B, Color, Origin3d, Stored, BufferUsageFlags, TextureUsageFlags, BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId, }; +use conv; use registry::{HUB, Items, Registry}; use track::{BufferTracker, TextureTracker}; +use std::iter; +use std::ops::Range; use std::thread::ThreadId; @@ -78,8 +82,49 @@ pub struct CommandBuffer { fence: B::Fence, recorded_thread_id: ThreadId, device_id: Stored, - buffer_tracker: BufferTracker, - texture_tracker: TextureTracker, + pub(crate) buffer_tracker: BufferTracker, + pub(crate) texture_tracker: TextureTracker, +} + +impl CommandBuffer { + pub(crate) fn insert_barriers( + raw: &mut ::CommandBuffer, + buffer_iter: I, + texture_iter: J, + ) where + I: Iterator)>, + J: Iterator)>, + { + let buffer_guard = HUB.buffers.lock(); + let texture_guard = HUB.textures.lock(); + + let buffer_barriers = buffer_iter.map(|(id, transit)| { + let b = buffer_guard.get(id); + trace!("transit {:?} {:?}", id, transit); + hal::memory::Barrier::Buffer { + states: conv::map_buffer_state(transit.start) .. + conv::map_buffer_state(transit.end), + target: &b.raw, + } + }); + let texture_barriers = texture_iter.map(|(id, transit)| { + let t = texture_guard.get(id); + trace!("transit {:?} {:?}", id, transit); + let aspects = t.full_range.aspects; + hal::memory::Barrier::Image { + states: conv::map_texture_state(transit.start, aspects) .. + conv::map_texture_state(transit.end, aspects), + target: &t.raw, + range: t.full_range.clone(), //TODO? + } + }); + + raw.pipeline_barrier( + hal::pso::PipelineStage::TOP_OF_PIPE .. hal::pso::PipelineStage::BOTTOM_OF_PIPE, + hal::memory::Dependencies::empty(), + buffer_barriers.chain(texture_barriers), + ); + } } #[repr(C)] @@ -88,27 +133,126 @@ pub struct CommandBufferDescriptor {} #[no_mangle] pub extern "C" fn wgpu_command_buffer_begin_render_pass( command_buffer_id: CommandBufferId, - _descriptor: RenderPassDescriptor, + desc: RenderPassDescriptor, ) -> RenderPassId { let mut cmb_guard = HUB.command_buffers.lock(); let cmb = cmb_guard.get_mut(command_buffer_id); - let device_guard = HUB.devices.lock(); let device = device_guard.get(cmb.device_id.0); + let view_guard = HUB.texture_views.lock(); - let current_comb = device.com_allocator.extend(cmb); + let mut current_comb = device.com_allocator.extend(cmb); + current_comb.begin( + hal::command::CommandBufferFlags::ONE_TIME_SUBMIT, + hal::command::CommandBufferInheritanceInfo::default(), + ); + let mut extent = None; - //let render_pass = device.create_render_pass(); - //let framebuffer = device.create_framebuffer(); + let render_pass = { + let tracker = &mut cmb.texture_tracker; - /*TODO: - raw.begin_render_pass( - render_pass: &B::RenderPass, - framebuffer: &B::Framebuffer, - render_area: pso::Rect, - clear_values: T, - hal::SubpassContents::Inline, - );*/ + let depth_stencil_attachment = match desc.depth_stencil_attachment { + Some(ref at) => { + let view = view_guard.get(at.attachment); + if let Some(ex) = extent { + assert_eq!(ex, view.extent); + } else { + extent = Some(view.extent); + } + let query = tracker.query(view.texture_id.0, TextureUsageFlags::empty()); + let (_, layout) = conv::map_texture_state( + query.usage, + hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL, + ); + Some(hal::pass::Attachment { + format: Some(conv::map_texture_format(view.format)), + samples: view.samples, + ops: conv::map_load_store_ops(at.depth_load_op, at.depth_store_op), + stencil_ops: conv::map_load_store_ops(at.stencil_load_op, at.stencil_store_op), + layouts: layout .. layout, + }) + } + None => None, + }; + let color_attachments = desc.color_attachments + .iter() + .map(|at| { + let view = view_guard.get(at.attachment); + if let Some(ex) = extent { + assert_eq!(ex, view.extent); + } else { + extent = Some(view.extent); + } + let query = tracker.query(view.texture_id.0, TextureUsageFlags::empty()); + let (_, layout) = conv::map_texture_state(query.usage, hal::format::Aspects::COLOR); + hal::pass::Attachment { + format: Some(conv::map_texture_format(view.format)), + samples: view.samples, + ops: conv::map_load_store_ops(at.load_op, at.store_op), + stencil_ops: hal::pass::AttachmentOps::DONT_CARE, + layouts: layout .. layout, + } + }); + let attachments = color_attachments.chain(depth_stencil_attachment); + + //TODO: retain the storage + let color_refs = (0 .. desc.color_attachments.len()) + .map(|i| { + (i, hal::image::Layout::ColorAttachmentOptimal) + }) + .collect::>(); + let ds_ref = desc.depth_stencil_attachment.as_ref().map(|_| { + (desc.color_attachments.len(), hal::image::Layout::DepthStencilAttachmentOptimal) + }); + let subpass = hal::pass::SubpassDesc { + colors: &color_refs, + depth_stencil: ds_ref.as_ref(), + inputs: &[], + resolves: &[], + preserves: &[], + }; + + device.raw.create_render_pass(attachments, iter::once(subpass), &[]) + }; + + let framebuffer = { + let attachments = desc.color_attachments + .iter() + .map(|at| at.attachment) + .chain(desc.depth_stencil_attachment.as_ref().map(|at| at.attachment)) + .map(|id| &view_guard.get(id).raw); + device.raw + .create_framebuffer(&render_pass, attachments, extent.unwrap()) + .unwrap() + }; + + let rect = { + let ex = extent.unwrap(); + hal::pso::Rect { + x: 0, + y: 0, + w: ex.width as _, + h: ex.height as _, + } + }; + let clear_values = desc.color_attachments + .iter() + .map(|at| { + //TODO: integer types? + let value = hal::command::ClearColor::Float(conv::map_color(at.clear_color)); + hal::command::ClearValueRaw::from(hal::command::ClearValue::Color(value)) + }) + .chain(desc.depth_stencil_attachment.map(|at| { + let value = hal::command::ClearDepthStencil(at.clear_depth, at.clear_stencil); + hal::command::ClearValueRaw::from(hal::command::ClearValue::DepthStencil(value)) + })); + current_comb.begin_render_pass( + &render_pass, + &framebuffer, + rect, + clear_values, + hal::command::SubpassContents::Inline, + ); HUB.render_passes .lock() diff --git a/wgpu-native/src/command/render.rs b/wgpu-native/src/command/render.rs index 88aa3310b1..417373173f 100644 --- a/wgpu-native/src/command/render.rs +++ b/wgpu-native/src/command/render.rs @@ -1,8 +1,7 @@ -use conv; use registry::{HUB, Items, Registry}; use track::{BufferTracker, TextureTracker}; use { - Stored, + CommandBuffer, Stored, CommandBufferId, RenderPassId, }; @@ -40,42 +39,17 @@ pub extern "C" fn wgpu_render_pass_end_pass( .take(pass_id); pass.raw.end_render_pass(); - let buffer_guard = HUB.buffers.lock(); - let texture_guard = HUB.textures.lock(); let mut cmb_guard = HUB.command_buffers.lock(); let cmb = cmb_guard.get_mut(pass.cmb_id.0); - let buffer_barriers = cmb.buffer_tracker - .consume(pass.buffer_tracker) - .map(|(id, transit)| { - let b = buffer_guard.get(id); - hal::memory::Barrier::Buffer { - states: conv::map_buffer_state(transit.start) .. - conv::map_buffer_state(transit.end), - target: &b.raw, - } - }); - let texture_barriers = cmb.texture_tracker - .consume(pass.texture_tracker) - .map(|(id, transit)| { - let t = texture_guard.get(id); - hal::memory::Barrier::Image { - states: conv::map_texture_state(transit.start, t.aspects) .. - conv::map_texture_state(transit.end, t.aspects), - target: &t.raw, - range: hal::image::SubresourceRange { //TODO! - aspects: t.aspects, - levels: 0 .. 1, - layers: 0 .. 1, - }, - } - }); - - pass.raw.pipeline_barrier( - hal::pso::PipelineStage::TOP_OF_PIPE .. hal::pso::PipelineStage::BOTTOM_OF_PIPE, - hal::memory::Dependencies::empty(), - buffer_barriers.chain(texture_barriers), - ); + if let Some(ref mut last) = cmb.raw.last_mut() { + CommandBuffer::insert_barriers( + last, + cmb.buffer_tracker.consume(&pass.buffer_tracker), + cmb.texture_tracker.consume(&pass.texture_tracker), + ); + last.finish(); + } cmb.raw.push(pass.raw); pass.cmb_id.0 diff --git a/wgpu-native/src/conv.rs b/wgpu-native/src/conv.rs index c266e1e8fb..de8b2946cd 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -1,6 +1,6 @@ use hal; -use {Extent3d, binding_model, pipeline, resource}; +use {Color, Extent3d, binding_model, command, pipeline, resource}; pub fn map_buffer_usage( @@ -277,11 +277,11 @@ fn checked_u32_as_u16(value: u32) -> u16 { } pub fn map_texture_dimension_size( - dimension: resource::TextureDimension, size: Extent3d + dimension: resource::TextureDimension, + Extent3d { width, height, depth }: Extent3d, ) -> hal::image::Kind { use hal::image::Kind as H; use resource::TextureDimension::*; - let Extent3d { width, height, depth } = size; match dimension { D1 => { assert_eq!(height, 1); @@ -292,6 +292,40 @@ pub fn map_texture_dimension_size( } } +pub fn map_texture_view_dimension( + dimension: resource::TextureViewDimension, +) -> hal::image::ViewKind { + use hal::image::ViewKind as H; + use resource::TextureViewDimension::*; + match dimension { + D1 => H::D1, + D2 => H::D2, + D2Array => H::D2Array, + Cube => H::Cube, + CubeArray => H::CubeArray, + D3 => H::D3, + } +} + +pub fn map_texture_aspect_flags( + aspect: resource::TextureAspectFlags +) -> hal::format::Aspects { + use resource::TextureAspectFlags as Taf; + use hal::format::Aspects; + + let mut flags = Aspects::empty(); + if aspect.contains(Taf::COLOR) { + flags |= Aspects::COLOR; + } + if aspect.contains(Taf::DEPTH) { + flags |= Aspects::DEPTH; + } + if aspect.contains(Taf::STENCIL) { + flags |= Aspects::STENCIL; + } + flags +} + pub fn map_buffer_state( usage: resource::BufferUsageFlags, ) -> hal::buffer::State { @@ -330,6 +364,7 @@ pub fn map_texture_state( let is_color = aspects.contains(hal::format::Aspects::COLOR); let layout = match usage { + W::WRITE_ALL => return (A::empty(), L::Undefined), // special value W::TRANSFER_SRC => L::TransferSrcOptimal, W::TRANSFER_DST => L::TransferDstOptimal, W::SAMPLED => L::ShaderReadOnlyOptimal, @@ -358,3 +393,19 @@ pub fn map_texture_state( (access, layout) } + +pub fn map_load_store_ops(load: command::LoadOp, store: command::StoreOp) -> hal::pass::AttachmentOps { + hal::pass::AttachmentOps { + load: match load { + command::LoadOp::Clear => hal::pass::AttachmentLoadOp::Clear, + command::LoadOp::Load => hal::pass::AttachmentLoadOp::Load, + }, + store: match store { + command::StoreOp::Store => hal::pass::AttachmentStoreOp::Store, + }, + } +} + +pub fn map_color(color: Color) -> hal::pso::ColorValue { + [color.r, color.g, color.b, color.a] +} diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 3c7c4e6ade..43f8a2dbd5 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -1,9 +1,11 @@ use {back, binding_model, command, conv, pipeline, resource}; use registry::{HUB, Items, Registry}; -use track::{BufferTracker, TextureTracker, TrackPermit}; +use track::{BufferTracker, TextureTracker}; use { + CommandBuffer, Stored, TextureUsageFlags, AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, - DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId, + DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, + TextureId, TextureViewId, }; use hal::command::RawCommandBuffer; @@ -68,6 +70,7 @@ pub(crate) struct ShaderModule { pub raw: B::ShaderModule, } + #[no_mangle] pub extern "C" fn wgpu_device_create_texture( device_id: DeviceId, @@ -109,21 +112,104 @@ pub extern "C" fn wgpu_device_create_texture( .bind_image_memory(&image_memory, 0, image_unbound) .unwrap(); + let full_range = hal::image::SubresourceRange { + aspects, + levels: 0 .. 1, //TODO: mips + layers: 0 .. 1, //TODO + }; + let id = HUB.textures .lock() .register(resource::Texture { raw: bound_image, - aspects, + device_id: Stored(device_id), + kind, + format: desc.format, + full_range, }); - device.texture_tracker + let query = device.texture_tracker .lock() .unwrap() - .track(id, resource::TextureUsageFlags::empty(), TrackPermit::empty()) - .expect("Resource somehow is already registered"); + .query(id, TextureUsageFlags::WRITE_ALL); + assert!(query.initialized); id } +#[no_mangle] +pub extern "C" fn wgpu_texture_create_texture_view( + texture_id: TextureId, + desc: &resource::TextureViewDescriptor, +) -> TextureViewId { + let texture_guard = HUB.textures.lock(); + let texture = texture_guard.get(texture_id); + + let raw = HUB.devices + .lock() + .get(texture.device_id.0) + .raw + .create_image_view( + &texture.raw, + conv::map_texture_view_dimension(desc.dimension), + conv::map_texture_format(desc.format), + hal::format::Swizzle::NO, + hal::image::SubresourceRange { + aspects: conv::map_texture_aspect_flags(desc.aspect), + levels: desc.base_mip_level as u8 .. (desc.base_mip_level + desc.level_count) as u8, + layers: desc.base_array_layer as u16 .. (desc.base_array_layer + desc.array_count) as u16, + }, + ) + .unwrap(); + + HUB.texture_views + .lock() + .register(resource::TextureView { + raw, + texture_id: Stored(texture_id), + format: texture.format, + extent: texture.kind.extent(), + samples: texture.kind.num_samples(), + }) +} + +#[no_mangle] +pub extern "C" fn wgpu_texture_create_default_texture_view( + texture_id: TextureId, +) -> TextureViewId { + let texture_guard = HUB.textures.lock(); + let texture = texture_guard.get(texture_id); + + let view_kind = match texture.kind { + hal::image::Kind::D1(..) => hal::image::ViewKind::D1, + hal::image::Kind::D2(..) => hal::image::ViewKind::D2, //TODO: array + hal::image::Kind::D3(..) => hal::image::ViewKind::D3, + }; + + let raw = HUB.devices + .lock() + .get(texture.device_id.0) + .raw + .create_image_view( + &texture.raw, + view_kind, + conv::map_texture_format(texture.format), + hal::format::Swizzle::NO, + texture.full_range.clone(), + ) + .unwrap(); + + HUB.texture_views + .lock() + .register(resource::TextureView { + raw, + texture_id: Stored(texture_id), + format: texture.format, + extent: texture.kind.extent(), + samples: texture.kind.num_samples(), + }) +} + + #[no_mangle] pub extern "C" fn wgpu_device_create_bind_group_layout( device_id: DeviceId, @@ -255,16 +341,34 @@ pub extern "C" fn wgpu_queue_submit( ) { let mut device_guard = HUB.devices.lock(); let device = device_guard.get_mut(queue_id); + let mut buffer_tracker = device.buffer_tracker.lock().unwrap(); + let mut texture_tracker = device.texture_tracker.lock().unwrap(); + let mut command_buffer_guard = HUB.command_buffers.lock(); let command_buffer_ids = unsafe { slice::from_raw_parts(command_buffer_ptr, command_buffer_count) }; + //TODO: if multiple command buffers are submitted, we can re-use the last + // native command buffer of the previous chain instead of always creating + // a temporary one, since the chains are not finished. + // finish all the command buffers first for &cmb_id in command_buffer_ids { - command_buffer_guard - .get_mut(cmb_id) - .raw + let comb = command_buffer_guard.get_mut(cmb_id); + let mut transit = device.com_allocator.extend(comb); + transit.begin( + hal::command::CommandBufferFlags::ONE_TIME_SUBMIT, + hal::command::CommandBufferInheritanceInfo::default(), + ); + CommandBuffer::insert_barriers( + &mut transit, + buffer_tracker.consume(&comb.buffer_tracker), + texture_tracker.consume(&comb.texture_tracker), + ); + transit.finish(); + comb.raw.insert(0, transit); + comb.raw .last_mut() .unwrap() .finish(); @@ -423,14 +527,14 @@ pub extern "C" fn wgpu_device_create_render_pipeline( }; let blend_state_guard = HUB.blend_states.lock(); - let blend_state = unsafe { slice::from_raw_parts(desc.blend_state, desc.blend_state_length) } + let blend_states = unsafe { slice::from_raw_parts(desc.blend_states, desc.blend_states_length) } .iter() .map(|id| blend_state_guard.get(id.clone()).raw) .collect(); let blender = hal::pso::BlendDesc { logic_op: None, // TODO - targets: blend_state, + targets: blend_states, }; let depth_stencil_state_guard = HUB.depth_stencil_states.lock(); diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index f1705c5bbe..e8a9996276 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -2,6 +2,8 @@ extern crate bitflags; #[macro_use] extern crate lazy_static; +#[macro_use] +extern crate log; #[cfg(feature = "remote")] extern crate parking_lot; @@ -100,6 +102,7 @@ type BufferHandle = Buffer; // Resource pub type TextureViewId = Id; +type TextureViewHandle = TextureView; pub type TextureId = Id; type TextureHandle = Texture; pub type SamplerId = Id; diff --git a/wgpu-native/src/pipeline.rs b/wgpu-native/src/pipeline.rs index a27c65cd9e..b0e4800b10 100644 --- a/wgpu-native/src/pipeline.rs +++ b/wgpu-native/src/pipeline.rs @@ -247,8 +247,8 @@ pub struct RenderPipelineDescriptor { pub stages: *const PipelineStageDescriptor, pub stages_length: usize, pub primitive_topology: PrimitiveTopology, - pub blend_state: *const BlendStateId, - pub blend_state_length: usize, + pub blend_states: *const BlendStateId, + pub blend_states_length: usize, pub depth_stencil_state: DepthStencilStateId, pub attachment_state: AttachmentStateId, } diff --git a/wgpu-native/src/registry/mod.rs b/wgpu-native/src/registry/mod.rs index 935732323f..5c5344efe8 100644 --- a/wgpu-native/src/registry/mod.rs +++ b/wgpu-native/src/registry/mod.rs @@ -13,7 +13,7 @@ use { BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle, RenderPassHandle, ComputePassHandle, PipelineLayoutHandle, RenderPipelineHandle, ComputePipelineHandle, ShaderModuleHandle, - BufferHandle, TextureHandle, + BufferHandle, TextureHandle, TextureViewHandle, }; @@ -50,6 +50,7 @@ pub struct Hub { pub(crate) compute_passes: ConcreteRegistry, pub(crate) buffers: ConcreteRegistry, pub(crate) textures: ConcreteRegistry, + pub(crate) texture_views: ConcreteRegistry, } lazy_static! { diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index 14df48e7a9..f914da45ae 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -1,4 +1,7 @@ -use {Extent3d}; +use { + Extent3d, Stored, + DeviceId, TextureId, +}; use hal; @@ -32,9 +35,6 @@ pub(crate) struct Buffer { // TODO: mapping, unmap() } -pub struct TextureView { - // TODO -} #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] @@ -78,9 +78,53 @@ pub struct TextureDescriptor { pub(crate) struct Texture { pub raw: B::Image, - pub aspects: hal::format::Aspects, + pub device_id: Stored, + pub kind: hal::image::Kind, + pub format: TextureFormat, + pub full_range: hal::image::SubresourceRange, } + +bitflags! { + #[repr(transparent)] + pub struct TextureAspectFlags: u32 { + const COLOR = 1; + const DEPTH = 2; + const STENCIL = 4; + } +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +pub enum TextureViewDimension { + D1, + D2, + D2Array, + Cube, + CubeArray, + D3, +} + +#[repr(C)] +pub struct TextureViewDescriptor { + pub format: TextureFormat, + pub dimension: TextureViewDimension, + pub aspect: TextureAspectFlags, + pub base_mip_level: u32, + pub level_count: u32, + pub base_array_layer: u32, + pub array_count: u32, +} + +pub(crate) struct TextureView { + pub raw: B::ImageView, + pub texture_id: Stored, + pub format: TextureFormat, + pub extent: hal::image::Extent, + pub samples: hal::image::NumSamples, +} + + #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum AddressMode { diff --git a/wgpu-native/src/track.rs b/wgpu-native/src/track.rs index 752e061161..a7428b3847 100644 --- a/wgpu-native/src/track.rs +++ b/wgpu-native/src/track.rs @@ -14,6 +14,12 @@ pub enum Tracktion { Replace { old: T }, } +#[derive(Clone, Debug, PartialEq)] +pub struct Query { + pub usage: T, + pub initialized: bool, +} + bitflags! { pub struct TrackPermit: u32 { const EXTEND = 1; @@ -37,8 +43,9 @@ impl GenericUsage for TextureUsageFlags { } +//TODO: consider having `I` as an associated type of `U`? pub struct Tracker { - map: HashMap, U>, + map: HashMap, Range>, } pub type BufferTracker = Tracker; pub type TextureTracker = Tracker; @@ -53,20 +60,40 @@ impl< } } - pub fn track(&mut self, id: I, usage: U, permit: TrackPermit) -> Result, U> { + pub fn query(&mut self, id: I, default: U) -> Query { match self.map.entry(Stored(id)) { Entry::Vacant(e) => { - e.insert(usage); + e.insert(default .. default); + Query { + usage: default, + initialized: true, + } + } + Entry::Occupied(e) => { + Query { + usage: e.get().end, + initialized: false, + } + } + } + } + + pub fn transit(&mut self, id: I, usage: U, permit: TrackPermit) -> Result, U> { + match self.map.entry(Stored(id)) { + Entry::Vacant(e) => { + e.insert(usage .. usage); Ok(Tracktion::Init) } Entry::Occupied(mut e) => { - let old = *e.get(); + let old = e.get().end; if usage == old { Ok(Tracktion::Keep) } else if permit.contains(TrackPermit::EXTEND) && !(old | usage).is_exclusive() { - Ok(Tracktion::Extend { old: e.insert(old | usage) }) + e.get_mut().end = old | usage; + Ok(Tracktion::Extend { old }) } else if permit.contains(TrackPermit::REPLACE) { - Ok(Tracktion::Replace { old: e.insert(usage) }) + e.get_mut().end = usage; + Ok(Tracktion::Replace { old }) } else { Err(old) } @@ -74,13 +101,13 @@ impl< } } - pub(crate) fn consume<'a>(&'a mut self, other: Self) -> impl 'a + Iterator)> { + pub fn consume<'a>(&'a mut self, other: &'a Self) -> impl 'a + Iterator)> { other.map - .into_iter() - .flat_map(move |(id, new)| match self.track(id.0.clone(), new, TrackPermit::REPLACE) { + .iter() + .flat_map(move |(id, new)| match self.transit(id.0.clone(), new.end, TrackPermit::REPLACE) { Ok(Tracktion::Init) | Ok(Tracktion::Keep) => None, - Ok(Tracktion::Replace { old }) => Some((id.0, old .. new)), + Ok(Tracktion::Replace { old }) => Some((id.0.clone(), old .. new.end)), Ok(Tracktion::Extend { .. }) | Err(_) => panic!("Unable to consume a resource transition!"), }) diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index 1a5bf14a20..ad7e11f608 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -8,10 +8,12 @@ use std::ffi::CString; pub use wgn::{ AdapterDescriptor, Color, CommandBufferDescriptor, DeviceDescriptor, Extensions, Extent3d, Origin3d, PowerPreference, ShaderModuleDescriptor, ShaderStage, - BindGroupLayoutBinding, TextureFormat, + BindGroupLayoutBinding, BindingType, TextureDimension, TextureDescriptor, TextureFormat, + TextureUsageFlags, TextureViewDescriptor, PrimitiveTopology, BlendStateDescriptor, ColorWriteFlags, DepthStencilStateDescriptor, RenderPassDescriptor, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, LoadOp, StoreOp, + ShaderStageFlags_NONE, ShaderStageFlags_VERTEX, ShaderStageFlags_FRAGMENT, ShaderStageFlags_COMPUTE }; @@ -27,6 +29,10 @@ pub struct Device { id: wgn::DeviceId, } +pub struct Texture { + id: wgn::TextureId, +} + pub struct TextureView { id: wgn::TextureViewId, } @@ -107,7 +113,7 @@ pub struct RenderPipelineDescriptor<'a> { pub layout: &'a PipelineLayout, pub stages: &'a [PipelineStageDescriptor<'a>], pub primitive_topology: PrimitiveTopology, - pub blend_state: &'a [&'a BlendState], + pub blend_states: &'a [&'a BlendState], pub depth_stencil_state: &'a DepthStencilState, pub attachment_state: &'a AttachmentState, } @@ -170,10 +176,15 @@ impl Device { } pub fn create_pipeline_layout(&self, desc: &PipelineLayoutDescriptor) -> PipelineLayout { + //TODO: avoid allocation here + let temp_layouts = desc.bind_group_layouts + .iter() + .map(|bgl| bgl.id) + .collect::>(); PipelineLayout { id: wgn::wgpu_device_create_pipeline_layout(self.id, &wgn::PipelineLayoutDescriptor { - bind_group_layouts: desc.bind_group_layouts.as_ptr() as *const _, - bind_group_layouts_length: desc.bind_group_layouts.len(), + bind_group_layouts: temp_layouts.as_ptr(), + bind_group_layouts_length: temp_layouts.len(), }), } } @@ -214,19 +225,44 @@ impl Device { }) .collect::>(); + let temp_blend_states = desc.blend_states + .iter() + .map(|bs| bs.id) + .collect::>(); + RenderPipeline { id: wgn::wgpu_device_create_render_pipeline(self.id, &wgn::RenderPipelineDescriptor { layout: desc.layout.id, stages: stages.as_ptr(), stages_length: stages.len(), primitive_topology: desc.primitive_topology, - blend_state: desc.blend_state.as_ptr() as *const _, - blend_state_length: desc.blend_state.len(), + blend_states: temp_blend_states.as_ptr(), + blend_states_length: temp_blend_states.len(), depth_stencil_state: desc.depth_stencil_state.id, attachment_state: desc.attachment_state.id, }), } } + + pub fn create_texture(&self, desc: &TextureDescriptor) -> Texture { + Texture { + id: wgn::wgpu_device_create_texture(self.id, &desc), + } + } +} + +impl Texture { + pub fn create_texture_view(&self, desc: &TextureViewDescriptor) -> TextureView { + TextureView { + id: wgn::wgpu_texture_create_texture_view(self.id, &desc), + } + } + + pub fn create_default_texture_view(&self) -> TextureView { + TextureView { + id: wgn::wgpu_texture_create_default_texture_view(self.id), + } + } } impl CommandBuffer {