mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
Buffer to texture copies
This commit is contained in:
parent
3ec4ff99b0
commit
d50f8199dd
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -154,6 +154,16 @@ name = "cfg-if"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cgmath"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.32.0"
|
||||
@ -443,6 +453,7 @@ dependencies = [
|
||||
name = "gfx-examples"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glsl-to-spirv 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1400,6 +1411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum cbindgen 0.6.8 (git+https://github.com/eqrion/cbindgen?rev=2932819)" = "<none>"
|
||||
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
|
||||
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
||||
"checksum cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "283944cdecc44bf0b8dd010ec9af888d3b4f142844fdbe026c20ef68148d6fe7"
|
||||
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a"
|
||||
|
@ -21,6 +21,7 @@ vulkan = ["wgpu-native/gfx-backend-vulkan"]
|
||||
[dependencies]
|
||||
wgpu-native = { path = "../wgpu-native" }
|
||||
wgpu = { path = "../wgpu-rs", features = ["winit"] }
|
||||
cgmath = "0.17"
|
||||
env_logger = "0.5"
|
||||
glsl-to-spirv = "0.1"
|
||||
log = "0.4"
|
||||
|
@ -1,3 +1,4 @@
|
||||
extern crate cgmath;
|
||||
extern crate wgpu;
|
||||
|
||||
#[path="framework.rs"]
|
||||
@ -85,16 +86,21 @@ impl fw::Example for Cube {
|
||||
size: (vertex_data.len() * vertex_size) as u32,
|
||||
usage: wgpu::BufferUsageFlags::VERTEX | wgpu::BufferUsageFlags::TRANSFER_DST,
|
||||
});
|
||||
vertex_buf.set_sub_data(0, unsafe { mem::transmute(&vertex_data[..]) });
|
||||
vertex_buf.set_sub_data(0, fw::cast_slice(&vertex_data));
|
||||
let index_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size: (index_data.len() * 2) as u32,
|
||||
usage: wgpu::BufferUsageFlags::INDEX | wgpu::BufferUsageFlags::TRANSFER_DST,
|
||||
});
|
||||
index_buf.set_sub_data(0, unsafe { mem::transmute(&index_data[..]) });
|
||||
index_buf.set_sub_data(0, fw::cast_slice(&index_data));
|
||||
|
||||
// Create pipeline layout
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStageFlags::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer,
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStageFlags::FRAGMENT,
|
||||
@ -113,12 +119,13 @@ impl fw::Example for Cube {
|
||||
|
||||
// Create the texture
|
||||
let texels = [0x20u8, 0xA0, 0xC0, 0xFF];
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
size: wgpu::Extent3d {
|
||||
let texture_extent = wgpu::Extent3d {
|
||||
width: 1,
|
||||
height: 1,
|
||||
depth: 1,
|
||||
},
|
||||
};
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
size: texture_extent,
|
||||
array_size: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::R8g8b8a8Unorm,
|
||||
@ -130,9 +137,27 @@ impl fw::Example for Cube {
|
||||
usage: wgpu::BufferUsageFlags::TRANSFER_SRC | wgpu::BufferUsageFlags::TRANSFER_DST
|
||||
});
|
||||
temp_buf.set_sub_data(0, &texels);
|
||||
//init_command_buf.copy_buffer_to_texture(); //TODO!
|
||||
init_command_buf.copy_buffer_to_texture(
|
||||
wgpu::BufferCopyView {
|
||||
buffer: &temp_buf,
|
||||
offset: 0,
|
||||
row_pitch: 4,
|
||||
image_height: 1,
|
||||
},
|
||||
wgpu::TextureCopyView {
|
||||
texture: &texture,
|
||||
level: 0,
|
||||
slice: 0,
|
||||
origin: wgpu::Origin3d {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
},
|
||||
},
|
||||
texture_extent,
|
||||
);
|
||||
|
||||
// Create the bind group
|
||||
// Create other resources
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
r_address_mode: wgpu::AddressMode::ClampToEdge,
|
||||
s_address_mode: wgpu::AddressMode::ClampToEdge,
|
||||
@ -146,15 +171,40 @@ impl fw::Example for Cube {
|
||||
compare_function: wgpu::CompareFunction::Always,
|
||||
border_color: wgpu::BorderColor::TransparentBlack,
|
||||
});
|
||||
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size: 64,
|
||||
usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST,
|
||||
});
|
||||
{
|
||||
let aspect_ratio = 1.0; //TODO
|
||||
let mx_projection = cgmath::perspective(cgmath::Deg(45f32), aspect_ratio, 1.0, 10.0);
|
||||
let mx_view = cgmath::Matrix4::look_at(
|
||||
cgmath::Point3::new(1.5f32, -5.0, 3.0),
|
||||
cgmath::Point3::new(0f32, 0.0, 0.0),
|
||||
cgmath::Vector3::unit_z(),
|
||||
);
|
||||
let mx_total = mx_projection * mx_view;
|
||||
let mx_raw: &[f32; 16] = mx_total.as_ref();
|
||||
vertex_buf.set_sub_data(0, fw::cast_slice(&mx_raw[..]));
|
||||
}
|
||||
|
||||
// Create bind group
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
bindings: &[
|
||||
wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(&texture_view),
|
||||
resource: wgpu::BindingResource::Buffer {
|
||||
buffer: &uniform_buf,
|
||||
range: 0 .. 64,
|
||||
},
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&texture_view),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::Sampler(&sampler),
|
||||
},
|
||||
],
|
||||
|
@ -10,6 +10,15 @@ use self::log::info;
|
||||
|
||||
pub const SWAP_CHAIN_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::B8g8r8a8Unorm;
|
||||
|
||||
pub fn cast_slice<T>(data: &[T]) -> &[u8] {
|
||||
use std::mem::size_of;
|
||||
use std::slice::from_raw_parts;
|
||||
|
||||
unsafe {
|
||||
from_raw_parts(data.as_ptr() as *const u8, data.len() * size_of::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_glsl_pair(name: &str) -> (Vec<u8>, Vec<u8>) {
|
||||
use self::glsl_to_spirv::{ShaderType, compile};
|
||||
use std::fs::read_to_string;
|
||||
|
@ -200,6 +200,34 @@ typedef struct {
|
||||
const WGPURenderPassDepthStencilAttachmentDescriptor_TextureViewId *depth_stencil_attachment;
|
||||
} WGPURenderPassDescriptor;
|
||||
|
||||
typedef struct {
|
||||
WGPUBufferId buffer;
|
||||
uint32_t offset;
|
||||
uint32_t row_pitch;
|
||||
uint32_t image_height;
|
||||
} WGPUBufferCopyView;
|
||||
|
||||
typedef WGPUId WGPUTextureId;
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} WGPUOrigin3d;
|
||||
|
||||
typedef struct {
|
||||
WGPUTextureId texture;
|
||||
uint32_t level;
|
||||
uint32_t slice;
|
||||
WGPUOrigin3d origin;
|
||||
} WGPUTextureCopyView;
|
||||
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t depth;
|
||||
} WGPUExtent3d;
|
||||
|
||||
typedef WGPUId WGPUBindGroupId;
|
||||
|
||||
typedef WGPUId WGPUComputePipelineId;
|
||||
@ -410,14 +438,6 @@ typedef struct {
|
||||
uint32_t height;
|
||||
} WGPUSwapChainDescriptor;
|
||||
|
||||
typedef WGPUId WGPUTextureId;
|
||||
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t depth;
|
||||
} WGPUExtent3d;
|
||||
|
||||
typedef struct {
|
||||
WGPUExtent3d size;
|
||||
uint32_t array_size;
|
||||
@ -536,6 +556,11 @@ WGPUComputePassId wgpu_command_buffer_begin_compute_pass(WGPUCommandBufferId com
|
||||
WGPURenderPassId wgpu_command_buffer_begin_render_pass(WGPUCommandBufferId command_buffer_id,
|
||||
WGPURenderPassDescriptor desc);
|
||||
|
||||
void wgpu_command_buffer_copy_buffer_to_texture(WGPUCommandBufferId command_buffer_id,
|
||||
const WGPUBufferCopyView *source,
|
||||
const WGPUTextureCopyView *destination,
|
||||
WGPUExtent3d copy_size);
|
||||
|
||||
void wgpu_compute_pass_dispatch(WGPUComputePassId pass_id, uint32_t x, uint32_t y, uint32_t z);
|
||||
|
||||
WGPUCommandBufferId wgpu_compute_pass_end_pass(WGPUComputePassId pass_id);
|
||||
|
@ -13,12 +13,13 @@ use crate::device::{
|
||||
};
|
||||
use crate::registry::{Items, HUB};
|
||||
use crate::swap_chain::{SwapChainLink, SwapImageEpoch};
|
||||
use crate::track::{BufferTracker, TextureTracker};
|
||||
use crate::track::{BufferTracker, TextureTracker, TrackPermit, Tracktion};
|
||||
use crate::{conv, resource};
|
||||
use crate::{
|
||||
BufferId, CommandBufferId, ComputePassId, DeviceId,
|
||||
RenderPassId, TextureId, TextureViewId,
|
||||
BufferUsageFlags, TextureUsageFlags, Color, Origin3d,
|
||||
BufferUsageFlags, TextureUsageFlags, Color,
|
||||
Extent3d, Origin3d,
|
||||
LifeGuard, Stored, WeaklyStored,
|
||||
B,
|
||||
};
|
||||
@ -379,3 +380,96 @@ pub extern "C" fn wgpu_command_buffer_begin_compute_pass(
|
||||
.write()
|
||||
.register(ComputePass::new(raw, stored))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture(
|
||||
command_buffer_id: CommandBufferId,
|
||||
source: &BufferCopyView,
|
||||
destination: &TextureCopyView,
|
||||
copy_size: Extent3d,
|
||||
) {
|
||||
let mut cmb_guard = HUB.command_buffers.write();
|
||||
let cmb = cmb_guard.get_mut(command_buffer_id);
|
||||
let buffer_guard = HUB.buffers.read();
|
||||
let texture_guard = HUB.textures.read();
|
||||
|
||||
let (src_buffer, src_tracktion) = cmb.buffer_tracker
|
||||
.get_with_usage(
|
||||
&*buffer_guard,
|
||||
source.buffer,
|
||||
BufferUsageFlags::TRANSFER_SRC,
|
||||
TrackPermit::REPLACE,
|
||||
)
|
||||
.unwrap();
|
||||
let src_barrier = match src_tracktion {
|
||||
Tracktion::Init |
|
||||
Tracktion::Keep => None,
|
||||
Tracktion::Extend { .. } => unreachable!(),
|
||||
Tracktion::Replace { old } => Some(hal::memory::Barrier::Buffer {
|
||||
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_WRITE,
|
||||
target: &src_buffer.raw,
|
||||
families: None,
|
||||
range: None .. None,
|
||||
}),
|
||||
};
|
||||
|
||||
let (dst_texture, dst_tracktion) = cmb.texture_tracker
|
||||
.get_with_usage(
|
||||
&*texture_guard,
|
||||
destination.texture,
|
||||
TextureUsageFlags::TRANSFER_DST,
|
||||
TrackPermit::REPLACE,
|
||||
)
|
||||
.unwrap();
|
||||
let aspects = dst_texture.full_range.aspects;
|
||||
let dst_texture_state = conv::map_texture_state(TextureUsageFlags::TRANSFER_DST, aspects);
|
||||
let dst_barrier = match dst_tracktion {
|
||||
Tracktion::Init |
|
||||
Tracktion::Keep => None,
|
||||
Tracktion::Extend { .. } => unreachable!(),
|
||||
Tracktion::Replace { old } => Some(hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(old, aspects) .. dst_texture_state,
|
||||
target: &dst_texture.raw,
|
||||
families: None,
|
||||
range: dst_texture.full_range.clone(),
|
||||
}),
|
||||
};
|
||||
|
||||
if let Some(ref link) = dst_texture.swap_chain_link {
|
||||
cmb.swap_chain_links.push(SwapChainLink {
|
||||
swap_chain_id: link.swap_chain_id.clone(),
|
||||
epoch: *link.epoch.lock(),
|
||||
image_index: link.image_index,
|
||||
});
|
||||
}
|
||||
|
||||
let bytes_per_texel = conv::map_texture_format(dst_texture.format).surface_desc().bits as u32 / 8;
|
||||
let buffer_width = source.row_pitch / bytes_per_texel;
|
||||
assert_eq!(source.row_pitch % bytes_per_texel, 0);
|
||||
let region = hal::command::BufferImageCopy {
|
||||
buffer_offset: source.offset as hal::buffer::Offset,
|
||||
buffer_width,
|
||||
buffer_height: source.image_height,
|
||||
image_layers: hal::image::SubresourceLayers {
|
||||
aspects, //TODO
|
||||
level: destination.level as hal::image::Level,
|
||||
layers: destination.slice as u16 .. destination.slice as u16 + 1,
|
||||
},
|
||||
image_offset: conv::map_origin(destination.origin),
|
||||
image_extent: conv::map_extent(copy_size),
|
||||
};
|
||||
let cmb_raw = cmb.raw.last_mut().unwrap();
|
||||
unsafe {
|
||||
cmb_raw.pipeline_barrier(
|
||||
all_buffer_stages() .. all_image_stages(),
|
||||
hal::memory::Dependencies::empty(),
|
||||
src_barrier.into_iter().chain(dst_barrier),
|
||||
);
|
||||
cmb_raw.copy_buffer_to_image(
|
||||
&src_buffer.raw,
|
||||
&dst_texture.raw,
|
||||
dst_texture_state.1,
|
||||
iter::once(region),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
use crate::{binding_model, command, pipeline, resource, Color, Extent3d};
|
||||
use crate::{
|
||||
binding_model, command, pipeline, resource, Color,
|
||||
Extent3d, Origin3d,
|
||||
};
|
||||
use log::warn;
|
||||
|
||||
|
||||
pub fn map_buffer_usage(
|
||||
usage: resource::BufferUsageFlags,
|
||||
) -> (hal::buffer::Usage, hal::memory::Properties) {
|
||||
@ -101,6 +105,22 @@ pub fn map_shader_stage_flags(
|
||||
value
|
||||
}
|
||||
|
||||
pub fn map_origin(origin: Origin3d) -> hal::image::Offset {
|
||||
hal::image::Offset {
|
||||
x: origin.x as i32,
|
||||
y: origin.y as i32,
|
||||
z: origin.z as i32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_extent(extent: Extent3d) -> hal::image::Extent {
|
||||
hal::image::Extent {
|
||||
width: extent.width,
|
||||
height: extent.height,
|
||||
depth: extent.depth,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_primitive_topology(primitive_topology: pipeline::PrimitiveTopology) -> hal::Primitive {
|
||||
use hal::Primitive as H;
|
||||
use crate::pipeline::PrimitiveTopology::*;
|
||||
|
@ -174,6 +174,43 @@ pub struct SwapChainOutput<'a> {
|
||||
swap_chain_id: &'a wgn::SwapChainId,
|
||||
}
|
||||
|
||||
pub struct BufferCopyView<'a> {
|
||||
pub buffer: &'a Buffer,
|
||||
pub offset: u32,
|
||||
pub row_pitch: u32,
|
||||
pub image_height: u32,
|
||||
}
|
||||
|
||||
impl<'a> BufferCopyView<'a> {
|
||||
fn into_native(self) -> wgn::BufferCopyView {
|
||||
wgn::BufferCopyView {
|
||||
buffer: self.buffer.id,
|
||||
offset: self.offset,
|
||||
row_pitch: self.row_pitch,
|
||||
image_height: self.image_height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TextureCopyView<'a> {
|
||||
pub texture: &'a Texture,
|
||||
pub level: u32,
|
||||
pub slice: u32,
|
||||
pub origin: Origin3d,
|
||||
}
|
||||
|
||||
impl<'a> TextureCopyView<'a> {
|
||||
fn into_native(self) -> wgn::TextureCopyView {
|
||||
wgn::TextureCopyView {
|
||||
texture: self.texture.id,
|
||||
level: self.level,
|
||||
slice: self.slice,
|
||||
origin: self.origin,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Instance {
|
||||
pub fn new() -> Self {
|
||||
Instance {
|
||||
@ -458,6 +495,20 @@ impl CommandBuffer {
|
||||
parent: self,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_buffer_to_texture(
|
||||
&mut self,
|
||||
source: BufferCopyView,
|
||||
destination: TextureCopyView,
|
||||
copy_size: Extent3d,
|
||||
) {
|
||||
wgn::wgpu_command_buffer_copy_buffer_to_texture(
|
||||
self.id,
|
||||
&source.into_native(),
|
||||
&destination.into_native(),
|
||||
copy_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RenderPass<'a> {
|
||||
|
Loading…
Reference in New Issue
Block a user