Buffer to texture copies

This commit is contained in:
Dzmitry Malyshau 2019-02-03 21:59:35 -05:00
parent 3ec4ff99b0
commit d50f8199dd
8 changed files with 283 additions and 21 deletions

12
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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_extent = wgpu::Extent3d {
width: 1,
height: 1,
depth: 1,
};
let texture = device.create_texture(&wgpu::TextureDescriptor {
size: wgpu::Extent3d {
width: 1,
height: 1,
depth: 1,
},
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),
},
],

View File

@ -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;

View File

@ -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);

View File

@ -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),
);
}
}

View File

@ -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::*;

View File

@ -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> {