Skip to content

Commit

Permalink
Merge gfx-rs#24
Browse files Browse the repository at this point in the history
24: Actually begin render passes r=grovesNL a=kvark

For now, we create the render pass and the frame buffer in place. Of course, we'd need to cache it properly, but this is blocked on W3C discussions on the API side.

With this PR, the Rust example is able to create a texture and run a render pass on it, all without a single Vulkan validation error 🎉 

Co-authored-by: Dzmitry Malyshau <dmalyshau@mozilla.com>
  • Loading branch information
bors[bot] and kvark committed Oct 28, 2018
2 parents 23e32b4 + f3cfd2e commit 5dcfd2b
Show file tree
Hide file tree
Showing 16 changed files with 514 additions and 97 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/hello_triangle_c/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
16 changes: 14 additions & 2 deletions examples/hello_triangle_rust/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -43,7 +56,7 @@ fn main() {
},
],
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
blend_state: &[
blend_states: &[
&blend_state0,
],
depth_stencil_state: &depth_stencil_state,
Expand All @@ -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 {
Expand Down
19 changes: 19 additions & 0 deletions examples/vk_layer_settings.txt
Original file line number Diff line number Diff line change
@@ -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
6 changes: 3 additions & 3 deletions wgpu-bindings/wgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions wgpu-native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
178 changes: 161 additions & 17 deletions wgpu-native/src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down Expand Up @@ -78,8 +82,49 @@ pub struct CommandBuffer<B: hal::Backend> {
fence: B::Fence,
recorded_thread_id: ThreadId,
device_id: Stored<DeviceId>,
buffer_tracker: BufferTracker,
texture_tracker: TextureTracker,
pub(crate) buffer_tracker: BufferTracker,
pub(crate) texture_tracker: TextureTracker,
}

impl CommandBuffer<B> {
pub(crate) fn insert_barriers<I, J>(
raw: &mut <B as hal::Backend>::CommandBuffer,
buffer_iter: I,
texture_iter: J,
) where
I: Iterator<Item = (BufferId, Range<BufferUsageFlags>)>,
J: Iterator<Item = (TextureId, Range<TextureUsageFlags>)>,
{
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)]
Expand All @@ -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<TextureViewId>,
desc: RenderPassDescriptor<TextureViewId>,
) -> 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 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 = {
let tracker = &mut cmb.texture_tracker;

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::<Vec<_>>();
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: &[],
};

let current_comb = device.com_allocator.extend(cmb);
device.raw.create_render_pass(attachments, iter::once(subpass), &[])
};

//let render_pass = device.create_render_pass();
//let framebuffer = device.create_framebuffer();
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()
};

/*TODO:
raw.begin_render_pass(
render_pass: &B::RenderPass,
framebuffer: &B::Framebuffer,
render_area: pso::Rect,
clear_values: T,
hal::SubpassContents::Inline,
);*/
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()
Expand Down
44 changes: 9 additions & 35 deletions wgpu-native/src/command/render.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use conv;
use registry::{HUB, Items, Registry};
use track::{BufferTracker, TextureTracker};
use {
Stored,
CommandBuffer, Stored,
CommandBufferId, RenderPassId,
};

Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 5dcfd2b

Please sign in to comment.