mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Merge #24
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>
This commit is contained in:
commit
5dcfd2bd6e
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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)",
|
||||
]
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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 {
|
||||
|
||||
19
examples/vk_layer_settings.txt
Normal file
19
examples/vk_layer_settings.txt
Normal file
@ -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
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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" }
|
||||
|
||||
@ -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<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)]
|
||||
@ -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 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::<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: &[],
|
||||
};
|
||||
|
||||
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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]
|
||||
}
|
||||
|
||||
@ -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<B: hal::Backend> {
|
||||
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();
|
||||
|
||||
@ -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<B>;
|
||||
|
||||
// Resource
|
||||
pub type TextureViewId = Id;
|
||||
type TextureViewHandle = TextureView<B>;
|
||||
pub type TextureId = Id;
|
||||
type TextureHandle = Texture<B>;
|
||||
pub type SamplerId = Id;
|
||||
|
||||
@ -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,
|
||||
}
|
||||
|
||||
@ -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<ComputePassHandle>,
|
||||
pub(crate) buffers: ConcreteRegistry<BufferHandle>,
|
||||
pub(crate) textures: ConcreteRegistry<TextureHandle>,
|
||||
pub(crate) texture_views: ConcreteRegistry<TextureViewHandle>,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
use {Extent3d};
|
||||
use {
|
||||
Extent3d, Stored,
|
||||
DeviceId, TextureId,
|
||||
};
|
||||
|
||||
use hal;
|
||||
|
||||
@ -32,9 +35,6 @@ pub(crate) struct Buffer<B: hal::Backend> {
|
||||
// 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<B: hal::Backend> {
|
||||
pub raw: B::Image,
|
||||
pub aspects: hal::format::Aspects,
|
||||
pub device_id: Stored<DeviceId>,
|
||||
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<B: hal::Backend> {
|
||||
pub raw: B::ImageView,
|
||||
pub texture_id: Stored<TextureId>,
|
||||
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 {
|
||||
|
||||
@ -14,6 +14,12 @@ pub enum Tracktion<T> {
|
||||
Replace { old: T },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Query<T> {
|
||||
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<I, U> {
|
||||
map: HashMap<Stored<I>, U>,
|
||||
map: HashMap<Stored<I>, Range<U>>,
|
||||
}
|
||||
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
|
||||
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
|
||||
@ -53,20 +60,40 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
pub fn track(&mut self, id: I, usage: U, permit: TrackPermit) -> Result<Tracktion<U>, U> {
|
||||
pub fn query(&mut self, id: I, default: U) -> Query<U> {
|
||||
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<Tracktion<U>, 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<Item = (I, Range<U>)> {
|
||||
pub fn consume<'a>(&'a mut self, other: &'a Self) -> impl 'a + Iterator<Item = (I, Range<U>)> {
|
||||
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!"),
|
||||
})
|
||||
|
||||
@ -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::<Vec<_>>();
|
||||
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::<ArrayVec<[_; 2]>>();
|
||||
|
||||
let temp_blend_states = desc.blend_states
|
||||
.iter()
|
||||
.map(|bs| bs.id)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user