mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Merge #23
23: State transitions for a render pass r=grovesNL a=kvark This PR introduces a simple resource tracker, which is used to build the pipeline barriers gluing the main command buffer with the one composed for the render pass contents. Render passes are still not started properly, blocked on the W3C discussion about the parameters. Co-authored-by: Dzmitry Malyshau <dmalyshau@mozilla.com>
This commit is contained in:
commit
23e32b41a0
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -82,7 +82,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cbindgen"
|
||||
version = "0.6.4"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1033,7 +1033,7 @@ dependencies = [
|
||||
name = "wgpu-bindings"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cbindgen 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cbindgen 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1139,7 +1139,7 @@ dependencies = [
|
||||
"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 byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781"
|
||||
"checksum cbindgen 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "33dfad88cda0bab90ef91c4ae338f132ba6934ea59b6e352eb96f558b5a879d7"
|
||||
"checksum cbindgen 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "660a462ad3acdc79f83dcc84161d9e87f01cb29754b7ab5196785e1f0c11f714"
|
||||
"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
|
||||
"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
|
||||
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
||||
|
||||
63
Makefile
Normal file
63
Makefile
Normal file
@ -0,0 +1,63 @@
|
||||
RUST_BACKTRACE:=1
|
||||
EXCLUDES:=
|
||||
FEATURE_RUST:=
|
||||
FEATURE_NATIVE:=
|
||||
|
||||
ifeq (,$(TARGET))
|
||||
CHECK_TARGET_FLAG=
|
||||
else
|
||||
CHECK_TARGET_FLAG=--target $(TARGET)
|
||||
endif
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
ifeq ($(TARGET),x86_64-pc-windows-gnu)
|
||||
FEATURE_RUST=vulkan
|
||||
FEATURE_NATIVE=gfx-backend-vulkan
|
||||
else
|
||||
FEATURE_RUST=dx12
|
||||
FEATURE_NATIVE=gfx-backend-dx12
|
||||
endif
|
||||
else
|
||||
UNAME_S:=$(shell uname -s)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
FEATURE_RUST=vulkan
|
||||
FEATURE_NATIVE=gfx-backend-vulkan
|
||||
endif
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
FEATURE_RUST=metal
|
||||
FEATURE_NATIVE=gfx-backend-metal
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: all check test doc clear lib-native lib-rust examples-native examples-rust
|
||||
|
||||
all: examples-native examples-rust
|
||||
|
||||
check:
|
||||
cargo check --all
|
||||
|
||||
test:
|
||||
cargo test --all --features "$(FEATURE_NATIVE) $(FEATURE_RUST)"
|
||||
|
||||
doc:
|
||||
cargo doc --all
|
||||
|
||||
clear:
|
||||
cargo clear
|
||||
rm wgpu-bindings/wgpu.h
|
||||
|
||||
lib-native: Cargo.lock wgpu-native/Cargo.toml $(wildcard wgpu-native/**/*.rs)
|
||||
cargo build --manifest-path wgpu-native/Cargo.toml --features $(FEATURE_NATIVE)
|
||||
|
||||
lib-rust: Cargo.lock wgpu-rs/Cargo.toml $(wildcard wgpu-rs/**/*.rs)
|
||||
cargo build --manifest-path wgpu-rs/Cargo.toml --features $(FEATURE_RUST)
|
||||
|
||||
wgpu-bindings/wgpu.h: Cargo.lock wgpu-bindings/src/*.rs lib-native
|
||||
cargo +nightly run --manifest-path wgpu-bindings/Cargo.toml
|
||||
|
||||
examples-native: lib-native wgpu-bindings/wgpu.h $(wildcard wgpu-native/**/*.c)
|
||||
$(MAKE) -C examples
|
||||
|
||||
examples-rust: lib-rust examples/Cargo.toml $(wildcard wgpu-native/**/*.rs)
|
||||
cargo build --manifest-path examples/Cargo.toml --bin hello_triangle --features $(FEATURE_RUST)
|
||||
@ -10,4 +10,4 @@ authors = [
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
cbindgen = "0.6.3"
|
||||
cbindgen = "0.6.6"
|
||||
|
||||
@ -11,8 +11,8 @@ const HEADER: &str = "
|
||||
";
|
||||
|
||||
fn main() {
|
||||
let mut crate_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
crate_dir.push("../wgpu-native");
|
||||
let crate_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let source_dir = crate_dir.parent().unwrap().join("wgpu-native");
|
||||
|
||||
let config = cbindgen::Config {
|
||||
header: Some(String::from(HEADER.trim())),
|
||||
@ -33,9 +33,10 @@ fn main() {
|
||||
};
|
||||
|
||||
cbindgen::Builder::new()
|
||||
.with_crate(crate_dir)
|
||||
.with_crate(source_dir)
|
||||
.with_config(config)
|
||||
.with_parse_expand(&["wgpu-native"])
|
||||
.generate()
|
||||
.unwrap()
|
||||
.write_to_file("wgpu.h");
|
||||
.write_to_file(crate_dir.join("wgpu.h"));
|
||||
}
|
||||
|
||||
@ -28,20 +28,6 @@
|
||||
|
||||
#define WGPUShaderStageFlags_VERTEX 1
|
||||
|
||||
#define WGPUTextureUsageFlags_NONE 0
|
||||
|
||||
#define WGPUTextureUsageFlags_OUTPUT_ATTACHMENT 16
|
||||
|
||||
#define WGPUTextureUsageFlags_PRESENT 32
|
||||
|
||||
#define WGPUTextureUsageFlags_SAMPLED 4
|
||||
|
||||
#define WGPUTextureUsageFlags_STORAGE 8
|
||||
|
||||
#define WGPUTextureUsageFlags_TRANSFER_DST 2
|
||||
|
||||
#define WGPUTextureUsageFlags_TRANSFER_SRC 1
|
||||
|
||||
typedef enum {
|
||||
WGPUBindingType_UniformBuffer = 0,
|
||||
WGPUBindingType_Sampler = 1,
|
||||
@ -276,12 +262,40 @@ typedef struct {
|
||||
|
||||
#define WGPUBLUE (Color){ .r = 0, .g = 0, .b = 1, .a = 1 }
|
||||
|
||||
#define WGPUEXTEND (TrackPermit){ .bits = 1 }
|
||||
|
||||
#define WGPUGREEN (Color){ .r = 0, .g = 1, .b = 0, .a = 1 }
|
||||
|
||||
#define WGPUINDEX (BufferUsageFlags){ .bits = 16 }
|
||||
|
||||
#define WGPUMAP_READ (BufferUsageFlags){ .bits = 1 }
|
||||
|
||||
#define WGPUMAP_WRITE (BufferUsageFlags){ .bits = 2 }
|
||||
|
||||
#define WGPUNONE (BufferUsageFlags){ .bits = 0 }
|
||||
|
||||
#define WGPUOUTPUT_ATTACHMENT (TextureUsageFlags){ .bits = 16 }
|
||||
|
||||
#define WGPUPRESENT (TextureUsageFlags){ .bits = 32 }
|
||||
|
||||
#define WGPURED (Color){ .r = 1, .g = 0, .b = 0, .a = 1 }
|
||||
|
||||
#define WGPUREPLACE (TrackPermit){ .bits = 2 }
|
||||
|
||||
#define WGPUSAMPLED (TextureUsageFlags){ .bits = 4 }
|
||||
|
||||
#define WGPUSTORAGE (BufferUsageFlags){ .bits = 128 }
|
||||
|
||||
#define WGPUTRANSFER_DST (BufferUsageFlags){ .bits = 8 }
|
||||
|
||||
#define WGPUTRANSFER_SRC (BufferUsageFlags){ .bits = 4 }
|
||||
|
||||
#define WGPUTRANSPARENT (Color){ .r = 0, .g = 0, .b = 0, .a = 0 }
|
||||
|
||||
#define WGPUUNIFORM (BufferUsageFlags){ .bits = 64 }
|
||||
|
||||
#define WGPUVERTEX (BufferUsageFlags){ .bits = 32 }
|
||||
|
||||
#define WGPUWHITE (Color){ .r = 1, .g = 1, .b = 1, .a = 1 }
|
||||
|
||||
WGPUDeviceId wgpu_adapter_create_device(WGPUAdapterId adapter_id,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use super::CommandBuffer;
|
||||
use {DeviceId, Stored};
|
||||
use track::{Tracker};
|
||||
|
||||
use hal::command::RawCommandBuffer;
|
||||
use hal::pool::RawCommandPool;
|
||||
@ -12,14 +13,37 @@ use std::thread;
|
||||
|
||||
struct CommandPool<B: hal::Backend> {
|
||||
raw: B::CommandPool,
|
||||
available: Vec<CommandBuffer<B>>,
|
||||
available: Vec<B::CommandBuffer>,
|
||||
}
|
||||
|
||||
impl<B: hal::Backend> CommandPool<B> {
|
||||
fn allocate(&mut self) -> B::CommandBuffer {
|
||||
if self.available.is_empty() {
|
||||
let extra = self.raw.allocate(20, hal::command::RawLevel::Primary);
|
||||
self.available.extend(extra);
|
||||
}
|
||||
|
||||
self.available.pop().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
struct Inner<B: hal::Backend> {
|
||||
pools: HashMap<thread::ThreadId, CommandPool<B>>,
|
||||
fences: Vec<B::Fence>,
|
||||
pending: Vec<CommandBuffer<B>>,
|
||||
}
|
||||
|
||||
impl<B: hal::Backend> Inner<B> {
|
||||
fn recycle(&mut self, cmd_buf: CommandBuffer<B>) {
|
||||
let pool = self.pools.get_mut(&cmd_buf.recorded_thread_id).unwrap();
|
||||
for mut raw in cmd_buf.raw {
|
||||
raw.reset(false);
|
||||
pool.available.push(raw);
|
||||
}
|
||||
self.fences.push(cmd_buf.fence);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommandAllocator<B: hal::Backend> {
|
||||
queue_family: hal::queue::QueueFamilyId,
|
||||
inner: Mutex<Inner<B>>,
|
||||
@ -31,6 +55,7 @@ impl<B: hal::Backend> CommandAllocator<B> {
|
||||
queue_family,
|
||||
inner: Mutex::new(Inner {
|
||||
pools: HashMap::new(),
|
||||
fences: Vec::new(),
|
||||
pending: Vec::new(),
|
||||
}),
|
||||
}
|
||||
@ -41,6 +66,17 @@ impl<B: hal::Backend> CommandAllocator<B> {
|
||||
) -> CommandBuffer<B> {
|
||||
let thread_id = thread::current().id();
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
|
||||
let fence = match inner.fences.pop() {
|
||||
Some(fence) => {
|
||||
device.reset_fence(&fence);
|
||||
fence
|
||||
}
|
||||
None => {
|
||||
device.create_fence(false)
|
||||
}
|
||||
};
|
||||
|
||||
let pool = inner.pools.entry(thread_id).or_insert_with(|| CommandPool {
|
||||
raw: device.create_command_pool(
|
||||
self.queue_family,
|
||||
@ -48,21 +84,27 @@ impl<B: hal::Backend> CommandAllocator<B> {
|
||||
),
|
||||
available: Vec::new(),
|
||||
});
|
||||
let init = pool.allocate();
|
||||
|
||||
if let Some(cmd_buf) = pool.available.pop() {
|
||||
assert_eq!(device_id, cmd_buf.device_id.0);
|
||||
device.reset_fence(&cmd_buf.fence);
|
||||
return cmd_buf;
|
||||
CommandBuffer {
|
||||
raw: vec![init],
|
||||
fence,
|
||||
recorded_thread_id: thread_id,
|
||||
device_id: Stored(device_id),
|
||||
buffer_tracker: Tracker::new(),
|
||||
texture_tracker: Tracker::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend(&self, cmd_buf: &CommandBuffer<B>) -> B::CommandBuffer {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let pool = inner.pools.get_mut(&cmd_buf.recorded_thread_id).unwrap();
|
||||
|
||||
if pool.available.is_empty() {
|
||||
let extra = pool.raw.allocate(20, hal::command::RawLevel::Primary);
|
||||
pool.available.extend(extra);
|
||||
}
|
||||
|
||||
for cmbuf in pool.raw.allocate(20, hal::command::RawLevel::Primary) {
|
||||
pool.available.push(CommandBuffer {
|
||||
raw: Some(cmbuf),
|
||||
fence: device.create_fence(false),
|
||||
recorded_thread_id: thread_id,
|
||||
device_id: Stored(device_id),
|
||||
});
|
||||
}
|
||||
pool.available.pop().unwrap()
|
||||
}
|
||||
|
||||
@ -70,16 +112,8 @@ impl<B: hal::Backend> CommandAllocator<B> {
|
||||
self.inner.lock().unwrap().pending.push(cmd_buf);
|
||||
}
|
||||
|
||||
pub fn recycle(&self, mut cmd_buf: CommandBuffer<B>) {
|
||||
cmd_buf.raw.as_mut().unwrap().reset(false);
|
||||
self.inner
|
||||
.lock()
|
||||
.unwrap()
|
||||
.pools
|
||||
.get_mut(&cmd_buf.recorded_thread_id)
|
||||
.unwrap()
|
||||
.available
|
||||
.push(cmd_buf);
|
||||
pub fn recycle(&self, cmd_buf: CommandBuffer<B>) {
|
||||
self.inner.lock().unwrap().recycle(cmd_buf);
|
||||
}
|
||||
|
||||
pub fn maintain(&self, device: &B::Device) {
|
||||
@ -87,12 +121,7 @@ impl<B: hal::Backend> CommandAllocator<B> {
|
||||
for i in (0..inner.pending.len()).rev() {
|
||||
if device.get_fence_status(&inner.pending[i].fence) {
|
||||
let cmd_buf = inner.pending.swap_remove(i);
|
||||
inner
|
||||
.pools
|
||||
.get_mut(&cmd_buf.recorded_thread_id)
|
||||
.unwrap()
|
||||
.available
|
||||
.push(cmd_buf);
|
||||
inner.recycle(cmd_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,8 @@ pub extern "C" fn wgpu_compute_pass_end_pass(
|
||||
HUB.command_buffers
|
||||
.lock()
|
||||
.get_mut(pass.cmb_id.0)
|
||||
.raw = Some(pass.raw);
|
||||
.raw
|
||||
.push(pass.raw);
|
||||
pass.cmb_id.0
|
||||
}
|
||||
|
||||
|
||||
@ -13,9 +13,11 @@ use {
|
||||
BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId,
|
||||
};
|
||||
use registry::{HUB, Items, Registry};
|
||||
use track::{BufferTracker, TextureTracker};
|
||||
|
||||
use std::thread::ThreadId;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum LoadOp {
|
||||
@ -72,10 +74,12 @@ pub struct TextureCopyView {
|
||||
}
|
||||
|
||||
pub struct CommandBuffer<B: hal::Backend> {
|
||||
pub(crate) raw: Option<B::CommandBuffer>,
|
||||
pub(crate) raw: Vec<B::CommandBuffer>,
|
||||
fence: B::Fence,
|
||||
recorded_thread_id: ThreadId,
|
||||
device_id: Stored<DeviceId>,
|
||||
buffer_tracker: BufferTracker,
|
||||
texture_tracker: TextureTracker,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -89,10 +93,10 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
||||
let mut cmb_guard = HUB.command_buffers.lock();
|
||||
let cmb = cmb_guard.get_mut(command_buffer_id);
|
||||
|
||||
let raw = cmb.raw.take().unwrap();
|
||||
|
||||
let device_guard = HUB.devices.lock();
|
||||
let _device = &device_guard.get(cmb.device_id.0).raw;
|
||||
let device = device_guard.get(cmb.device_id.0);
|
||||
|
||||
let current_comb = device.com_allocator.extend(cmb);
|
||||
|
||||
//let render_pass = device.create_render_pass();
|
||||
//let framebuffer = device.create_framebuffer();
|
||||
@ -108,7 +112,10 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
||||
|
||||
HUB.render_passes
|
||||
.lock()
|
||||
.register(RenderPass::new(raw, command_buffer_id))
|
||||
.register(RenderPass::new(
|
||||
current_comb,
|
||||
command_buffer_id,
|
||||
))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -118,7 +125,7 @@ pub extern "C" fn wgpu_command_buffer_begin_compute_pass(
|
||||
let mut cmb_guard = HUB.command_buffers.lock();
|
||||
let cmb = cmb_guard.get_mut(command_buffer_id);
|
||||
|
||||
let raw = cmb.raw.take().unwrap();
|
||||
let raw = cmb.raw.pop().unwrap();
|
||||
|
||||
HUB.compute_passes
|
||||
.lock()
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
use conv;
|
||||
use registry::{HUB, Items, Registry};
|
||||
use track::{BufferTracker, TextureTracker};
|
||||
use {
|
||||
Stored,
|
||||
CommandBufferId, RenderPassId,
|
||||
@ -11,13 +13,20 @@ use hal::command::RawCommandBuffer;
|
||||
pub struct RenderPass<B: hal::Backend> {
|
||||
raw: B::CommandBuffer,
|
||||
cmb_id: Stored<CommandBufferId>,
|
||||
buffer_tracker: BufferTracker,
|
||||
texture_tracker: TextureTracker,
|
||||
}
|
||||
|
||||
impl<B: hal::Backend> RenderPass<B> {
|
||||
pub fn new(raw: B::CommandBuffer, cmb_id: CommandBufferId) -> Self {
|
||||
pub fn new(
|
||||
raw: B::CommandBuffer,
|
||||
cmb_id: CommandBufferId,
|
||||
) -> Self {
|
||||
RenderPass {
|
||||
raw,
|
||||
cmb_id: Stored(cmb_id),
|
||||
buffer_tracker: BufferTracker::new(),
|
||||
texture_tracker: TextureTracker::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,9 +40,43 @@ pub extern "C" fn wgpu_render_pass_end_pass(
|
||||
.take(pass_id);
|
||||
pass.raw.end_render_pass();
|
||||
|
||||
HUB.command_buffers
|
||||
.lock()
|
||||
.get_mut(pass.cmb_id.0)
|
||||
.raw = Some(pass.raw);
|
||||
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),
|
||||
);
|
||||
|
||||
cmb.raw.push(pass.raw);
|
||||
pass.cmb_id.0
|
||||
}
|
||||
|
||||
@ -2,7 +2,8 @@ use hal;
|
||||
|
||||
use {Extent3d, binding_model, pipeline, resource};
|
||||
|
||||
pub(crate) fn map_buffer_usage(
|
||||
|
||||
pub fn map_buffer_usage(
|
||||
usage: resource::BufferUsageFlags,
|
||||
) -> (hal::buffer::Usage, hal::memory::Properties) {
|
||||
use hal::buffer::Usage as U;
|
||||
@ -40,7 +41,38 @@ pub(crate) fn map_buffer_usage(
|
||||
(hal_usage, hal_memory)
|
||||
}
|
||||
|
||||
pub(crate) fn map_binding_type(
|
||||
pub fn map_texture_usage(
|
||||
usage: resource::TextureUsageFlags, aspects: hal::format::Aspects
|
||||
) -> hal::image::Usage {
|
||||
use hal::image::Usage as U;
|
||||
use resource::TextureUsageFlags as W;
|
||||
|
||||
let mut value = U::empty();
|
||||
if usage.contains(W::TRANSFER_SRC) {
|
||||
value |= U::TRANSFER_SRC;
|
||||
}
|
||||
if usage.contains(W::TRANSFER_DST) {
|
||||
value |= U::TRANSFER_DST;
|
||||
}
|
||||
if usage.contains(W::SAMPLED) {
|
||||
value |= U::SAMPLED;
|
||||
}
|
||||
if usage.contains(W::STORAGE) {
|
||||
value |= U::STORAGE;
|
||||
}
|
||||
if usage.contains(W::OUTPUT_ATTACHMENT) {
|
||||
if aspects.intersects(hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL) {
|
||||
value |= U::DEPTH_STENCIL_ATTACHMENT;
|
||||
} else {
|
||||
value |= U::COLOR_ATTACHMENT;
|
||||
}
|
||||
}
|
||||
// Note: TextureUsageFlags::Present does not need to be handled explicitly
|
||||
// TODO: HAL Transient Attachment, HAL Input Attachment
|
||||
value
|
||||
}
|
||||
|
||||
pub fn map_binding_type(
|
||||
binding_ty: binding_model::BindingType,
|
||||
) -> hal::pso::DescriptorType {
|
||||
use binding_model::BindingType::*;
|
||||
@ -53,7 +85,7 @@ pub(crate) fn map_binding_type(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_shader_stage_flags(
|
||||
pub fn map_shader_stage_flags(
|
||||
shader_stage_flags: binding_model::ShaderStageFlags,
|
||||
) -> hal::pso::ShaderStageFlags {
|
||||
use binding_model::{
|
||||
@ -73,7 +105,7 @@ pub(crate) fn map_shader_stage_flags(
|
||||
value
|
||||
}
|
||||
|
||||
pub(crate) fn map_primitive_topology(
|
||||
pub fn map_primitive_topology(
|
||||
primitive_topology: pipeline::PrimitiveTopology,
|
||||
) -> hal::Primitive {
|
||||
use hal::Primitive as H;
|
||||
@ -87,7 +119,7 @@ pub(crate) fn map_primitive_topology(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_blend_state_descriptor(
|
||||
pub fn map_blend_state_descriptor(
|
||||
desc: &pipeline::BlendStateDescriptor,
|
||||
) -> hal::pso::ColorBlendDesc {
|
||||
let color_mask = desc.write_mask;
|
||||
@ -164,7 +196,7 @@ fn map_blend_factor(blend_factor: pipeline::BlendFactor) -> hal::pso::Factor {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_depth_stencil_state(
|
||||
pub fn map_depth_stencil_state(
|
||||
desc: &pipeline::DepthStencilStateDescriptor,
|
||||
) -> hal::pso::DepthStencilDesc {
|
||||
hal::pso::DepthStencilDesc {
|
||||
@ -228,7 +260,7 @@ fn map_stencil_operation(stencil_operation: pipeline::StencilOperation) -> hal::
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_texture_format(texture_format: resource::TextureFormat) -> hal::format::Format {
|
||||
pub fn map_texture_format(texture_format: resource::TextureFormat) -> hal::format::Format {
|
||||
use hal::format::Format as H;
|
||||
use resource::TextureFormat::*;
|
||||
match texture_format {
|
||||
@ -244,7 +276,9 @@ fn checked_u32_as_u16(value: u32) -> u16 {
|
||||
value as u16
|
||||
}
|
||||
|
||||
pub(crate) fn map_texture_dimension_size(dimension: resource::TextureDimension, size: Extent3d) -> hal::image::Kind {
|
||||
pub fn map_texture_dimension_size(
|
||||
dimension: resource::TextureDimension, size: Extent3d
|
||||
) -> hal::image::Kind {
|
||||
use hal::image::Kind as H;
|
||||
use resource::TextureDimension::*;
|
||||
let Extent3d { width, height, depth } = size;
|
||||
@ -258,33 +292,69 @@ pub(crate) fn map_texture_dimension_size(dimension: resource::TextureDimension,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn map_texture_usage_flags(flags: u32, format: hal::format::Format) -> hal::image::Usage {
|
||||
use hal::image::Usage as H;
|
||||
use resource::{
|
||||
TextureUsageFlags_TRANSFER_SRC, TextureUsageFlags_TRANSFER_DST, TextureUsageFlags_SAMPLED,
|
||||
TextureUsageFlags_STORAGE, TextureUsageFlags_OUTPUT_ATTACHMENT,
|
||||
};
|
||||
let mut value = H::empty();
|
||||
if 0 != flags & TextureUsageFlags_TRANSFER_SRC {
|
||||
value |= H::TRANSFER_SRC;
|
||||
pub fn map_buffer_state(
|
||||
usage: resource::BufferUsageFlags,
|
||||
) -> hal::buffer::State {
|
||||
use hal::buffer::Access as A;
|
||||
use resource::BufferUsageFlags as W;
|
||||
|
||||
let mut access = A::empty();
|
||||
if usage.contains(W::TRANSFER_SRC) {
|
||||
access |= A::TRANSFER_READ;
|
||||
}
|
||||
if 0 != flags & TextureUsageFlags_TRANSFER_DST {
|
||||
value |= H::TRANSFER_DST;
|
||||
if usage.contains(W::TRANSFER_DST) {
|
||||
access |= A::TRANSFER_WRITE;
|
||||
}
|
||||
if 0 != flags & TextureUsageFlags_SAMPLED {
|
||||
value |= H::SAMPLED;
|
||||
if usage.contains(W::INDEX) {
|
||||
access |= A::INDEX_BUFFER_READ;
|
||||
}
|
||||
if 0 != flags & TextureUsageFlags_STORAGE {
|
||||
value |= H::STORAGE;
|
||||
if usage.contains(W::VERTEX) {
|
||||
access |= A::VERTEX_BUFFER_READ;
|
||||
}
|
||||
if 0 != flags & TextureUsageFlags_OUTPUT_ATTACHMENT {
|
||||
if format.surface_desc().aspects.intersects(hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL) {
|
||||
value |= H::DEPTH_STENCIL_ATTACHMENT;
|
||||
} else {
|
||||
value |= H::COLOR_ATTACHMENT;
|
||||
}
|
||||
if usage.contains(W::UNIFORM) {
|
||||
access |= A::CONSTANT_BUFFER_READ | A::SHADER_READ;
|
||||
}
|
||||
// Note: TextureUsageFlags::Present does not need to be handled explicitly
|
||||
// TODO: HAL Transient Attachment, HAL Input Attachment
|
||||
value
|
||||
if usage.contains(W::STORAGE) {
|
||||
access |= A::SHADER_WRITE;
|
||||
}
|
||||
|
||||
access
|
||||
}
|
||||
|
||||
pub fn map_texture_state(
|
||||
usage: resource::TextureUsageFlags,
|
||||
aspects: hal::format::Aspects,
|
||||
) -> hal::image::State {
|
||||
use hal::image::{Access as A, Layout as L};
|
||||
use resource::TextureUsageFlags as W;
|
||||
|
||||
let is_color = aspects.contains(hal::format::Aspects::COLOR);
|
||||
let layout = match usage {
|
||||
W::TRANSFER_SRC => L::TransferSrcOptimal,
|
||||
W::TRANSFER_DST => L::TransferDstOptimal,
|
||||
W::SAMPLED => L::ShaderReadOnlyOptimal,
|
||||
W::OUTPUT_ATTACHMENT if is_color => L::ColorAttachmentOptimal,
|
||||
W::OUTPUT_ATTACHMENT => L::DepthStencilAttachmentOptimal, //TODO: read-only depth/stencil
|
||||
_ => L::General,
|
||||
};
|
||||
|
||||
let mut access = A::empty();
|
||||
if usage.contains(W::TRANSFER_SRC) {
|
||||
access |= A::TRANSFER_READ;
|
||||
}
|
||||
if usage.contains(W::TRANSFER_DST) {
|
||||
access |= A::TRANSFER_WRITE;
|
||||
}
|
||||
if usage.contains(W::SAMPLED) {
|
||||
access |= A::SHADER_READ;
|
||||
}
|
||||
if usage.contains(W::STORAGE) {
|
||||
access |= A::SHADER_WRITE;
|
||||
}
|
||||
if usage.contains(W::OUTPUT_ATTACHMENT) {
|
||||
//TODO: read-only attachments
|
||||
access |= if is_color { A::COLOR_ATTACHMENT_WRITE } else { A::DEPTH_STENCIL_ATTACHMENT_WRITE };
|
||||
}
|
||||
|
||||
(access, layout)
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use {back, binding_model, command, conv, pipeline, resource};
|
||||
use registry::{HUB, Items, Registry};
|
||||
use track::{BufferTracker, TextureTracker, TrackPermit};
|
||||
use {
|
||||
AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId,
|
||||
DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId,
|
||||
@ -8,16 +9,19 @@ use {
|
||||
use hal::command::RawCommandBuffer;
|
||||
use hal::queue::RawCommandQueue;
|
||||
use hal::{self, Device as _Device};
|
||||
use rendy_memory::{allocator, Config, Heaps};
|
||||
|
||||
use std::{ffi, slice};
|
||||
use rendy_memory::{allocator, Config, Heaps};
|
||||
use std::sync::Mutex;
|
||||
|
||||
|
||||
pub struct Device<B: hal::Backend> {
|
||||
pub(crate) raw: B::Device,
|
||||
queue_group: hal::QueueGroup<B, hal::General>,
|
||||
mem_allocator: Heaps<B::Memory>,
|
||||
com_allocator: command::CommandAllocator<B>,
|
||||
pub(crate) com_allocator: command::CommandAllocator<B>,
|
||||
buffer_tracker: Mutex<BufferTracker>,
|
||||
texture_tracker: Mutex<TextureTracker>,
|
||||
mem_props: hal::MemoryProperties,
|
||||
}
|
||||
|
||||
@ -53,6 +57,8 @@ impl<B: hal::Backend> Device<B> {
|
||||
mem_allocator,
|
||||
com_allocator: command::CommandAllocator::new(queue_group.family()),
|
||||
queue_group,
|
||||
buffer_tracker: Mutex::new(BufferTracker::new()),
|
||||
texture_tracker: Mutex::new(TextureTracker::new()),
|
||||
mem_props,
|
||||
}
|
||||
}
|
||||
@ -69,7 +75,8 @@ pub extern "C" fn wgpu_device_create_texture(
|
||||
) -> TextureId {
|
||||
let kind = conv::map_texture_dimension_size(desc.dimension, desc.size);
|
||||
let format = conv::map_texture_format(desc.format);
|
||||
let usage = conv::map_texture_usage_flags(desc.usage, format);
|
||||
let aspects = format.surface_desc().aspects;
|
||||
let usage = conv::map_texture_usage(desc.usage, aspects);
|
||||
let device_guard = HUB.devices.lock();
|
||||
let device = &device_guard.get(device_id);
|
||||
let image_unbound = device
|
||||
@ -101,11 +108,20 @@ pub extern "C" fn wgpu_device_create_texture(
|
||||
.raw
|
||||
.bind_image_memory(&image_memory, 0, image_unbound)
|
||||
.unwrap();
|
||||
HUB.textures
|
||||
|
||||
let id = HUB.textures
|
||||
.lock()
|
||||
.register(resource::Texture {
|
||||
raw: bound_image,
|
||||
})
|
||||
aspects,
|
||||
});
|
||||
device.texture_tracker
|
||||
.lock()
|
||||
.unwrap()
|
||||
.track(id, resource::TextureUsageFlags::empty(), TrackPermit::empty())
|
||||
.expect("Resource somehow is already registered");
|
||||
|
||||
id
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -215,11 +231,11 @@ pub extern "C" fn wgpu_device_create_command_buffer(
|
||||
device_id: DeviceId,
|
||||
_desc: &command::CommandBufferDescriptor,
|
||||
) -> CommandBufferId {
|
||||
let mut device_guard = HUB.devices.lock();
|
||||
let device = device_guard.get_mut(device_id);
|
||||
let device_guard = HUB.devices.lock();
|
||||
let device = device_guard.get(device_id);
|
||||
|
||||
let mut cmd_buf = device.com_allocator.allocate(device_id, &device.raw);
|
||||
cmd_buf.raw.as_mut().unwrap().begin(
|
||||
cmd_buf.raw.last_mut().unwrap().begin(
|
||||
hal::command::CommandBufferFlags::ONE_TIME_SUBMIT,
|
||||
hal::command::CommandBufferInheritanceInfo::default(),
|
||||
);
|
||||
@ -249,7 +265,7 @@ pub extern "C" fn wgpu_queue_submit(
|
||||
command_buffer_guard
|
||||
.get_mut(cmb_id)
|
||||
.raw
|
||||
.as_mut()
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.finish();
|
||||
}
|
||||
@ -259,12 +275,8 @@ pub extern "C" fn wgpu_queue_submit(
|
||||
let submission = hal::queue::RawSubmission {
|
||||
cmd_buffers: command_buffer_ids
|
||||
.iter()
|
||||
.map(|&cmb_id| {
|
||||
command_buffer_guard
|
||||
.get(cmb_id)
|
||||
.raw
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.flat_map(|&cmb_id| {
|
||||
&command_buffer_guard.get(cmb_id).raw
|
||||
}),
|
||||
wait_semaphores: &[],
|
||||
signal_semaphores: &[],
|
||||
|
||||
@ -29,6 +29,7 @@ mod instance;
|
||||
mod pipeline;
|
||||
mod registry;
|
||||
mod resource;
|
||||
mod track;
|
||||
|
||||
pub use self::binding_model::*;
|
||||
pub use self::command::*;
|
||||
@ -40,7 +41,7 @@ pub use self::resource::*;
|
||||
use back::Backend as B;
|
||||
use registry::Id;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
struct Stored<T>(T);
|
||||
#[cfg(not(feature = "remote"))]
|
||||
unsafe impl<T> Sync for Stored<T> {}
|
||||
@ -95,6 +96,7 @@ pub type DeviceId = Id;
|
||||
type DeviceHandle = Device<B>;
|
||||
pub type QueueId = Id;
|
||||
pub type BufferId = Id;
|
||||
type BufferHandle = Buffer<B>;
|
||||
|
||||
// Resource
|
||||
pub type TextureViewId = Id;
|
||||
|
||||
@ -13,7 +13,7 @@ use {
|
||||
BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle,
|
||||
RenderPassHandle, ComputePassHandle,
|
||||
PipelineLayoutHandle, RenderPipelineHandle, ComputePipelineHandle, ShaderModuleHandle,
|
||||
TextureHandle,
|
||||
BufferHandle, TextureHandle,
|
||||
};
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ pub struct Hub {
|
||||
pub(crate) compute_pipelines: ConcreteRegistry<ComputePipelineHandle>,
|
||||
pub(crate) render_passes: ConcreteRegistry<RenderPassHandle>,
|
||||
pub(crate) compute_passes: ConcreteRegistry<ComputePassHandle>,
|
||||
pub(crate) buffers: ConcreteRegistry<BufferHandle>,
|
||||
pub(crate) textures: ConcreteRegistry<TextureHandle>,
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use {Extent3d};
|
||||
|
||||
use hal;
|
||||
|
||||
use Extent3d;
|
||||
|
||||
bitflags! {
|
||||
#[repr(transparent)]
|
||||
pub struct BufferUsageFlags: u32 {
|
||||
const NONE = 0;
|
||||
const MAP_READ = 1;
|
||||
const MAP_WRITE = 2;
|
||||
const TRANSFER_SRC = 4;
|
||||
@ -14,6 +14,8 @@ bitflags! {
|
||||
const VERTEX = 32;
|
||||
const UNIFORM = 64;
|
||||
const STORAGE = 128;
|
||||
const NONE = 0;
|
||||
const WRITE_ALL = 2 + 8 + 128;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,9 +25,10 @@ pub struct BufferDescriptor {
|
||||
pub usage: BufferUsageFlags,
|
||||
}
|
||||
|
||||
pub struct Buffer<B: hal::Backend> {
|
||||
pub(crate) raw: B::UnboundBuffer,
|
||||
pub(crate) memory_properties: hal::memory::Properties,
|
||||
pub(crate) struct Buffer<B: hal::Backend> {
|
||||
//pub raw: B::UnboundBuffer,
|
||||
pub raw: B::Buffer,
|
||||
pub memory_properties: hal::memory::Properties,
|
||||
// TODO: mapping, unmap()
|
||||
}
|
||||
|
||||
@ -50,22 +53,19 @@ pub enum TextureFormat {
|
||||
D32FloatS8Uint = 3,
|
||||
}
|
||||
|
||||
// TODO: bitflags
|
||||
pub type TextureUsageFlags = u32;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const TextureUsageFlags_NONE: u32 = 0;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const TextureUsageFlags_TRANSFER_SRC: u32 = 1;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const TextureUsageFlags_TRANSFER_DST: u32 = 2;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const TextureUsageFlags_SAMPLED: u32 = 4;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const TextureUsageFlags_STORAGE: u32 = 8;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const TextureUsageFlags_OUTPUT_ATTACHMENT: u32 = 16;
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const TextureUsageFlags_PRESENT: u32 = 32;
|
||||
bitflags! {
|
||||
#[repr(transparent)]
|
||||
pub struct TextureUsageFlags: u32 {
|
||||
const TRANSFER_SRC = 1;
|
||||
const TRANSFER_DST = 2;
|
||||
const SAMPLED = 4;
|
||||
const STORAGE = 8;
|
||||
const OUTPUT_ATTACHMENT = 16;
|
||||
const PRESENT = 32;
|
||||
const NONE = 0;
|
||||
const WRITE_ALL = 2 + 8 + 16;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct TextureDescriptor {
|
||||
@ -76,8 +76,9 @@ pub struct TextureDescriptor {
|
||||
pub usage: TextureUsageFlags,
|
||||
}
|
||||
|
||||
pub struct Texture<B: hal::Backend> {
|
||||
pub(crate) raw: B::Image,
|
||||
pub(crate) struct Texture<B: hal::Backend> {
|
||||
pub raw: B::Image,
|
||||
pub aspects: hal::format::Aspects,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
||||
88
wgpu-native/src/track.rs
Normal file
88
wgpu-native/src/track.rs
Normal file
@ -0,0 +1,88 @@
|
||||
use {Stored, BufferId, TextureId};
|
||||
use resource::{BufferUsageFlags, TextureUsageFlags};
|
||||
|
||||
use std::collections::hash_map::{Entry, HashMap};
|
||||
use std::hash::Hash;
|
||||
use std::ops::{BitOr, Range};
|
||||
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Tracktion<T> {
|
||||
Init,
|
||||
Keep,
|
||||
Extend { old: T },
|
||||
Replace { old: T },
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct TrackPermit: u32 {
|
||||
const EXTEND = 1;
|
||||
const REPLACE = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait GenericUsage {
|
||||
fn is_exclusive(&self) -> bool;
|
||||
}
|
||||
impl GenericUsage for BufferUsageFlags {
|
||||
fn is_exclusive(&self) -> bool {
|
||||
BufferUsageFlags::WRITE_ALL.intersects(*self)
|
||||
}
|
||||
}
|
||||
impl GenericUsage for TextureUsageFlags {
|
||||
fn is_exclusive(&self) -> bool {
|
||||
TextureUsageFlags::WRITE_ALL.intersects(*self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct Tracker<I, U> {
|
||||
map: HashMap<Stored<I>, U>,
|
||||
}
|
||||
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
|
||||
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
|
||||
|
||||
impl<
|
||||
I: Clone + Hash + Eq,
|
||||
U: Copy + GenericUsage + BitOr<Output = U> + PartialEq,
|
||||
> Tracker<I, U> {
|
||||
pub fn new() -> Self {
|
||||
Tracker {
|
||||
map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn track(&mut self, id: I, usage: U, permit: TrackPermit) -> Result<Tracktion<U>, U> {
|
||||
match self.map.entry(Stored(id)) {
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(usage);
|
||||
Ok(Tracktion::Init)
|
||||
}
|
||||
Entry::Occupied(mut e) => {
|
||||
let old = *e.get();
|
||||
if usage == old {
|
||||
Ok(Tracktion::Keep)
|
||||
} else if permit.contains(TrackPermit::EXTEND) && !(old | usage).is_exclusive() {
|
||||
Ok(Tracktion::Extend { old: e.insert(old | usage) })
|
||||
} else if permit.contains(TrackPermit::REPLACE) {
|
||||
Ok(Tracktion::Replace { old: e.insert(usage) })
|
||||
} else {
|
||||
Err(old)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn consume<'a>(&'a mut self, other: 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) {
|
||||
Ok(Tracktion::Init) |
|
||||
Ok(Tracktion::Keep) => None,
|
||||
Ok(Tracktion::Replace { old }) => Some((id.0, old .. new)),
|
||||
Ok(Tracktion::Extend { .. }) |
|
||||
Err(_) => panic!("Unable to consume a resource transition!"),
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user