mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
hal: make copy to work on one array layer at a time
This commit is contained in:
parent
f79c3781c3
commit
35ee65707f
@ -120,27 +120,34 @@ pub(crate) fn extract_texture_selector<A: hal::Api>(
|
||||
});
|
||||
}
|
||||
|
||||
let layers = match texture.desc.dimension {
|
||||
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => {
|
||||
copy_texture.origin.z..copy_texture.origin.z + copy_size.depth_or_array_layers
|
||||
}
|
||||
wgt::TextureDimension::D3 => 0..1,
|
||||
let (layers, origin_z) = match texture.desc.dimension {
|
||||
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => (
|
||||
copy_texture.origin.z..copy_texture.origin.z + copy_size.depth_or_array_layers,
|
||||
0,
|
||||
),
|
||||
wgt::TextureDimension::D3 => (0..1, copy_texture.origin.z),
|
||||
};
|
||||
let base = hal::TextureCopyBase {
|
||||
origin: wgt::Origin3d {
|
||||
x: copy_texture.origin.x,
|
||||
y: copy_texture.origin.y,
|
||||
z: origin_z,
|
||||
},
|
||||
// this value will be incremented per copied layer
|
||||
array_layer: layers.start,
|
||||
mip_level: copy_texture.mip_level,
|
||||
aspect: copy_aspect,
|
||||
};
|
||||
let selector = TextureSelector {
|
||||
levels: copy_texture.mip_level..copy_texture.mip_level + 1,
|
||||
layers,
|
||||
};
|
||||
let base = hal::TextureCopyBase {
|
||||
origin: copy_texture.origin,
|
||||
mip_level: copy_texture.mip_level,
|
||||
aspect: copy_aspect,
|
||||
};
|
||||
|
||||
Ok((selector, base, format))
|
||||
}
|
||||
|
||||
/// Function copied with some modifications from webgpu standard <https://gpuweb.github.io/gpuweb/#copy-between-buffer-texture>
|
||||
/// If successful, returns number of buffer bytes required for this copy.
|
||||
/// If successful, returns (number of buffer bytes required for this copy, number of bytes between array layers).
|
||||
pub(crate) fn validate_linear_texture_data(
|
||||
layout: &wgt::ImageDataLayout,
|
||||
format: wgt::TextureFormat,
|
||||
@ -149,7 +156,7 @@ pub(crate) fn validate_linear_texture_data(
|
||||
bytes_per_block: BufferAddress,
|
||||
copy_size: &Extent3d,
|
||||
need_copy_aligned_rows: bool,
|
||||
) -> Result<BufferAddress, TransferError> {
|
||||
) -> Result<(BufferAddress, BufferAddress), TransferError> {
|
||||
// Convert all inputs to BufferAddress (u64) to prevent overflow issues
|
||||
let copy_width = copy_size.width as BufferAddress;
|
||||
let copy_height = copy_size.height as BufferAddress;
|
||||
@ -202,10 +209,10 @@ pub(crate) fn validate_linear_texture_data(
|
||||
}
|
||||
|
||||
let bytes_in_last_row = block_size * width_in_blocks;
|
||||
let bytes_per_image = bytes_per_row * block_rows_per_image;
|
||||
let required_bytes_in_copy = if copy_width == 0 || copy_height == 0 || copy_depth == 0 {
|
||||
0
|
||||
} else {
|
||||
let bytes_per_image = bytes_per_row * block_rows_per_image;
|
||||
let bytes_in_last_slice = bytes_per_row * (height_in_blocks - 1) + bytes_in_last_row;
|
||||
bytes_per_image * (copy_depth - 1) + bytes_in_last_slice
|
||||
};
|
||||
@ -227,17 +234,17 @@ pub(crate) fn validate_linear_texture_data(
|
||||
if copy_height > 1 && bytes_per_row < bytes_in_last_row {
|
||||
return Err(TransferError::InvalidBytesPerRow);
|
||||
}
|
||||
Ok(required_bytes_in_copy)
|
||||
Ok((required_bytes_in_copy, bytes_per_image))
|
||||
}
|
||||
|
||||
/// Function copied with minor modifications from webgpu standard <https://gpuweb.github.io/gpuweb/#valid-texture-copy-range>
|
||||
/// Returns the (virtual) mip level extent.
|
||||
/// Returns the HAL copy extent and the layer count.
|
||||
pub(crate) fn validate_texture_copy_range(
|
||||
texture_copy_view: &ImageCopyTexture,
|
||||
desc: &wgt::TextureDescriptor<()>,
|
||||
texture_side: CopySide,
|
||||
copy_size: &Extent3d,
|
||||
) -> Result<Extent3d, TransferError> {
|
||||
) -> Result<(hal::CopyExtent, u32), TransferError> {
|
||||
let (block_width, block_height) = desc.format.describe().block_dimensions;
|
||||
let block_width = block_width as u32;
|
||||
let block_height = block_height as u32;
|
||||
@ -295,7 +302,28 @@ pub(crate) fn validate_texture_copy_range(
|
||||
return Err(TransferError::UnalignedCopyHeight);
|
||||
}
|
||||
|
||||
Ok(extent_virtual)
|
||||
let (depth, array_layer_count) = match desc.dimension {
|
||||
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => {
|
||||
(1, copy_size.depth_or_array_layers)
|
||||
}
|
||||
wgt::TextureDimension::D3 => (
|
||||
copy_size
|
||||
.depth_or_array_layers
|
||||
.min(extent_virtual.depth_or_array_layers),
|
||||
1,
|
||||
),
|
||||
};
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let copy_extent = hal::CopyExtent {
|
||||
width: copy_size.width.min(extent_virtual.width),
|
||||
height: copy_size.width.min(extent_virtual.height),
|
||||
depth,
|
||||
};
|
||||
Ok((copy_extent, array_layer_count))
|
||||
}
|
||||
|
||||
impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
@ -505,13 +533,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let dst_barriers = dst_pending.map(|pending| pending.into_hal(dst_texture));
|
||||
|
||||
let format_desc = dst_texture.desc.format.describe();
|
||||
let max_image_extent = validate_texture_copy_range(
|
||||
let (hal_copy_size, array_layer_count) = validate_texture_copy_range(
|
||||
destination,
|
||||
&dst_texture.desc,
|
||||
CopySide::Destination,
|
||||
copy_size,
|
||||
)?;
|
||||
let required_buffer_bytes_in_copy = validate_linear_texture_data(
|
||||
let (required_buffer_bytes_in_copy, bytes_per_array_layer) = validate_linear_texture_data(
|
||||
&source.layout,
|
||||
dst_texture.desc.format,
|
||||
src_buffer.size,
|
||||
@ -538,24 +566,22 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
);
|
||||
}
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let region = hal::BufferTextureCopy {
|
||||
buffer_layout: source.layout,
|
||||
texture_base: dst_base,
|
||||
size: Extent3d {
|
||||
width: copy_size.width.min(max_image_extent.width),
|
||||
height: copy_size.height.min(max_image_extent.height),
|
||||
depth_or_array_layers: copy_size.depth_or_array_layers,
|
||||
},
|
||||
};
|
||||
let regions = (0..array_layer_count).map(|rel_array_layer| {
|
||||
let mut texture_base = dst_base.clone();
|
||||
texture_base.array_layer += rel_array_layer;
|
||||
let mut buffer_layout = source.layout;
|
||||
buffer_layout.offset += rel_array_layer as u64 * bytes_per_array_layer;
|
||||
hal::BufferTextureCopy {
|
||||
buffer_layout,
|
||||
texture_base,
|
||||
size: hal_copy_size,
|
||||
}
|
||||
});
|
||||
let cmd_buf_raw = cmd_buf.encoder.open();
|
||||
unsafe {
|
||||
cmd_buf_raw.transition_buffers(src_barriers);
|
||||
cmd_buf_raw.transition_textures(dst_barriers);
|
||||
cmd_buf_raw.copy_buffer_to_texture(src_raw, dst_raw, iter::once(region));
|
||||
cmd_buf_raw.copy_buffer_to_texture(src_raw, dst_raw, regions);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -635,9 +661,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let dst_barriers = dst_pending.map(|pending| pending.into_hal(dst_buffer));
|
||||
|
||||
let format_desc = src_texture.desc.format.describe();
|
||||
let max_image_extent =
|
||||
let (hal_copy_size, array_layer_count) =
|
||||
validate_texture_copy_range(source, &src_texture.desc, CopySide::Source, copy_size)?;
|
||||
let required_buffer_bytes_in_copy = validate_linear_texture_data(
|
||||
let (required_buffer_bytes_in_copy, bytes_per_array_layer) = validate_linear_texture_data(
|
||||
&destination.layout,
|
||||
src_texture.desc.format,
|
||||
dst_buffer.size,
|
||||
@ -667,19 +693,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}),
|
||||
);
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let region = hal::BufferTextureCopy {
|
||||
buffer_layout: destination.layout,
|
||||
texture_base: src_base,
|
||||
size: Extent3d {
|
||||
width: copy_size.width.min(max_image_extent.width),
|
||||
height: copy_size.height.min(max_image_extent.height),
|
||||
depth_or_array_layers: copy_size.depth_or_array_layers,
|
||||
},
|
||||
};
|
||||
let regions = (0..array_layer_count).map(|rel_array_layer| {
|
||||
let mut texture_base = src_base.clone();
|
||||
texture_base.array_layer += rel_array_layer;
|
||||
let mut buffer_layout = destination.layout;
|
||||
buffer_layout.offset += rel_array_layer as u64 * bytes_per_array_layer;
|
||||
hal::BufferTextureCopy {
|
||||
buffer_layout,
|
||||
texture_base,
|
||||
size: hal_copy_size,
|
||||
}
|
||||
});
|
||||
let cmd_buf_raw = cmd_buf.encoder.open();
|
||||
unsafe {
|
||||
cmd_buf_raw.transition_buffers(dst_barriers);
|
||||
@ -688,7 +712,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
src_raw,
|
||||
hal::TextureUses::COPY_SRC,
|
||||
dst_raw,
|
||||
iter::once(region),
|
||||
regions,
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
@ -725,11 +749,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (src_range, src_base, _) =
|
||||
let (src_range, src_tex_base, _) =
|
||||
extract_texture_selector(source, copy_size, &*texture_guard)?;
|
||||
let (dst_range, dst_base, _) =
|
||||
let (dst_range, dst_tex_base, _) =
|
||||
extract_texture_selector(destination, copy_size, &*texture_guard)?;
|
||||
if src_base.aspect != dst_base.aspect {
|
||||
if src_tex_base.aspect != dst_tex_base.aspect {
|
||||
return Err(TransferError::MismatchedAspects.into());
|
||||
}
|
||||
|
||||
@ -777,32 +801,31 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}
|
||||
barriers.extend(dst_pending.map(|pending| pending.into_hal(dst_texture)));
|
||||
|
||||
let max_src_image_extent =
|
||||
let (src_copy_size, array_layer_count) =
|
||||
validate_texture_copy_range(source, &src_texture.desc, CopySide::Source, copy_size)?;
|
||||
let max_dst_image_extent = validate_texture_copy_range(
|
||||
let (dst_copy_size, _) = validate_texture_copy_range(
|
||||
destination,
|
||||
&dst_texture.desc,
|
||||
CopySide::Destination,
|
||||
copy_size,
|
||||
)?;
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let region = hal::TextureCopy {
|
||||
src_base,
|
||||
dst_base,
|
||||
size: Extent3d {
|
||||
width: copy_size
|
||||
.width
|
||||
.min(max_src_image_extent.width.min(max_dst_image_extent.width)),
|
||||
height: copy_size
|
||||
.height
|
||||
.min(max_src_image_extent.height.min(max_dst_image_extent.height)),
|
||||
depth_or_array_layers: copy_size.depth_or_array_layers,
|
||||
},
|
||||
let hal_copy_size = hal::CopyExtent {
|
||||
width: src_copy_size.width.min(dst_copy_size.width),
|
||||
height: src_copy_size.height.min(dst_copy_size.height),
|
||||
depth: src_copy_size.depth.min(dst_copy_size.depth),
|
||||
};
|
||||
let regions = (0..array_layer_count).map(|rel_array_layer| {
|
||||
let mut src_base = src_tex_base.clone();
|
||||
let mut dst_base = dst_tex_base.clone();
|
||||
src_base.array_layer += rel_array_layer;
|
||||
dst_base.array_layer += rel_array_layer;
|
||||
hal::TextureCopy {
|
||||
src_base,
|
||||
dst_base,
|
||||
size: hal_copy_size,
|
||||
}
|
||||
});
|
||||
let cmd_buf_raw = cmd_buf.encoder.open();
|
||||
unsafe {
|
||||
cmd_buf_raw.transition_textures(barriers.into_iter());
|
||||
@ -810,7 +833,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
src_raw,
|
||||
hal::TextureUses::COPY_SRC,
|
||||
dst_raw,
|
||||
iter::once(region),
|
||||
regions,
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
|
@ -732,10 +732,13 @@ impl<A: HalApi> Device<A> {
|
||||
let usage = {
|
||||
let mask_copy = !(hal::TextureUses::COPY_SRC | hal::TextureUses::COPY_DST);
|
||||
let mask_dimension = match view_dim {
|
||||
wgt::TextureViewDimension::Cube |
|
||||
wgt::TextureViewDimension::CubeArray => hal::TextureUses::SAMPLED,
|
||||
wgt::TextureViewDimension::Cube | wgt::TextureViewDimension::CubeArray => {
|
||||
hal::TextureUses::SAMPLED
|
||||
}
|
||||
wgt::TextureViewDimension::D3 => {
|
||||
hal::TextureUses::SAMPLED | hal::TextureUses::STORAGE_LOAD | hal::TextureUses::STORAGE_STORE
|
||||
hal::TextureUses::SAMPLED
|
||||
| hal::TextureUses::STORAGE_LOAD
|
||||
| hal::TextureUses::STORAGE_STORE
|
||||
}
|
||||
_ => hal::TextureUses::all(),
|
||||
};
|
||||
@ -747,7 +750,11 @@ impl<A: HalApi> Device<A> {
|
||||
texture.hal_usage & mask_copy & mask_dimension & mask_mip_level
|
||||
};
|
||||
|
||||
log::debug!("Create view for texture {:?} filters usages to {:?}", texture_id, usage);
|
||||
log::debug!(
|
||||
"Create view for texture {:?} filters usages to {:?}",
|
||||
texture_id,
|
||||
usage
|
||||
);
|
||||
let hal_desc = hal::TextureViewDescriptor {
|
||||
label: desc.label.borrow_option(),
|
||||
format,
|
||||
|
@ -433,10 +433,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}
|
||||
|
||||
let (texture_guard, _) = hub.textures.read(&mut token);
|
||||
let (selector, texture_base, texture_format) =
|
||||
let (selector, dst_base, texture_format) =
|
||||
extract_texture_selector(destination, size, &*texture_guard)?;
|
||||
let format_desc = texture_format.describe();
|
||||
validate_linear_texture_data(
|
||||
let (_, bytes_per_array_layer) = validate_linear_texture_data(
|
||||
data_layout,
|
||||
texture_format,
|
||||
data.len() as wgt::BufferAddress,
|
||||
@ -495,7 +495,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
TransferError::MissingCopyDstUsageFlag(None, Some(destination.texture)).into(),
|
||||
);
|
||||
}
|
||||
let max_image_extent =
|
||||
let (hal_copy_size, array_layer_count) =
|
||||
validate_texture_copy_range(destination, &dst.desc, CopySide::Destination, size)?;
|
||||
dst.life_guard.use_at(device.active_submission_index + 1);
|
||||
|
||||
@ -542,33 +542,29 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.map_err(DeviceError::from)?;
|
||||
}
|
||||
|
||||
// WebGPU uses the physical size of the texture for copies whereas vulkan uses
|
||||
// the virtual size. We have passed validation, so it's safe to use the
|
||||
// image extent data directly. We want the provided copy size to be no larger than
|
||||
// the virtual size.
|
||||
let region = hal::BufferTextureCopy {
|
||||
buffer_layout: wgt::ImageDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: NonZeroU32::new(stage_bytes_per_row),
|
||||
rows_per_image: NonZeroU32::new(block_rows_per_image),
|
||||
},
|
||||
texture_base,
|
||||
size: wgt::Extent3d {
|
||||
width: size.width.min(max_image_extent.width),
|
||||
height: size.height.min(max_image_extent.height),
|
||||
depth_or_array_layers: size.depth_or_array_layers,
|
||||
},
|
||||
};
|
||||
|
||||
let regions = (0..array_layer_count).map(|rel_array_layer| {
|
||||
let mut texture_base = dst_base.clone();
|
||||
texture_base.array_layer += rel_array_layer;
|
||||
hal::BufferTextureCopy {
|
||||
buffer_layout: wgt::ImageDataLayout {
|
||||
offset: rel_array_layer as u64 * bytes_per_array_layer,
|
||||
bytes_per_row: NonZeroU32::new(stage_bytes_per_row),
|
||||
rows_per_image: NonZeroU32::new(block_rows_per_image),
|
||||
},
|
||||
texture_base,
|
||||
size: hal_copy_size,
|
||||
}
|
||||
});
|
||||
let barrier = hal::BufferBarrier {
|
||||
buffer: &stage.buffer,
|
||||
usage: hal::BufferUses::MAP_WRITE..hal::BufferUses::COPY_SRC,
|
||||
};
|
||||
|
||||
let encoder = device.pending_writes.activate();
|
||||
unsafe {
|
||||
encoder.transition_buffers(iter::once(barrier));
|
||||
encoder.transition_textures(transition.map(|pending| pending.into_hal(dst)));
|
||||
encoder.copy_buffer_to_texture(&stage.buffer, dst_raw, iter::once(region));
|
||||
encoder.copy_buffer_to_texture(&stage.buffer, dst_raw, regions);
|
||||
}
|
||||
|
||||
device.pending_writes.consume(stage);
|
||||
|
@ -302,9 +302,14 @@ impl<A: hal::Api> Example<A> {
|
||||
texture_base: hal::TextureCopyBase {
|
||||
origin: wgt::Origin3d::ZERO,
|
||||
mip_level: 0,
|
||||
array_layer: 0,
|
||||
aspect: hal::FormatAspects::COLOR,
|
||||
},
|
||||
size: texture_desc.size,
|
||||
size: hal::CopyExtent {
|
||||
width: 1,
|
||||
height: 1,
|
||||
depth: 1,
|
||||
},
|
||||
};
|
||||
unsafe {
|
||||
cmd_encoder.transition_buffers(iter::once(buffer_barrier));
|
||||
|
@ -210,59 +210,26 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
};
|
||||
|
||||
for r in regions {
|
||||
let (
|
||||
depth,
|
||||
array_layer_count,
|
||||
src_z,
|
||||
src_base_array_layer,
|
||||
dst_z,
|
||||
dst_base_array_layer,
|
||||
) = match src.dimension {
|
||||
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => (
|
||||
1,
|
||||
r.size.depth_or_array_layers,
|
||||
0,
|
||||
r.src_base.origin.z,
|
||||
0,
|
||||
r.dst_base.origin.z,
|
||||
),
|
||||
wgt::TextureDimension::D3 => (
|
||||
r.size.depth_or_array_layers,
|
||||
1,
|
||||
r.src_base.origin.z,
|
||||
0,
|
||||
r.dst_base.origin.z,
|
||||
0,
|
||||
),
|
||||
};
|
||||
let src_box = d3d12::D3D12_BOX {
|
||||
left: r.src_base.origin.x,
|
||||
top: r.src_base.origin.y,
|
||||
right: r.src_base.origin.x + r.size.width,
|
||||
bottom: r.src_base.origin.y + r.size.height,
|
||||
front: src_z,
|
||||
back: src_z + depth,
|
||||
front: r.src_base.origin.z,
|
||||
back: r.src_base.origin.z + r.size.depth,
|
||||
};
|
||||
for rel_array_layer in 0..array_layer_count {
|
||||
*src_location.u.SubresourceIndex_mut() = src.calc_subresource(
|
||||
r.src_base.mip_level,
|
||||
src_base_array_layer + rel_array_layer,
|
||||
0,
|
||||
);
|
||||
*dst_location.u.SubresourceIndex_mut() = dst.calc_subresource(
|
||||
r.dst_base.mip_level,
|
||||
dst_base_array_layer + rel_array_layer,
|
||||
0,
|
||||
);
|
||||
list.CopyTextureRegion(
|
||||
&dst_location,
|
||||
r.dst_base.origin.x,
|
||||
r.dst_base.origin.y,
|
||||
dst_z,
|
||||
&src_location,
|
||||
&src_box,
|
||||
);
|
||||
}
|
||||
*src_location.u.SubresourceIndex_mut() =
|
||||
src.calc_subresource(r.src_base.mip_level, r.src_base.array_layer, 0);
|
||||
*dst_location.u.SubresourceIndex_mut() =
|
||||
dst.calc_subresource(r.dst_base.mip_level, r.dst_base.array_layer, 0);
|
||||
list.CopyTextureRegion(
|
||||
&dst_location,
|
||||
r.dst_base.origin.x,
|
||||
r.dst_base.origin.y,
|
||||
r.dst_base.origin.z,
|
||||
&src_location,
|
||||
&src_box,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,14 +252,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
) where
|
||||
T: Iterator<Item = crate::BufferTextureCopy>,
|
||||
{
|
||||
for r in regions {
|
||||
let (_base_array_layer, _array_layer_count) = match src.dimension {
|
||||
wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => {
|
||||
(r.texture_base.origin.z, r.size.depth_or_array_layers)
|
||||
}
|
||||
wgt::TextureDimension::D3 => (0, 1),
|
||||
};
|
||||
}
|
||||
for _r in regions {}
|
||||
}
|
||||
|
||||
unsafe fn begin_query(&mut self, set: &super::QuerySet, index: u32) {}
|
||||
|
@ -201,52 +201,51 @@ impl super::Queue {
|
||||
ref copy,
|
||||
} => {
|
||||
//TODO: cubemaps
|
||||
//TODO: how is depth handled?
|
||||
//TODO: handle 3D copies
|
||||
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(self.copy_fbo));
|
||||
for layer in 0..copy.size.depth_or_array_layers as i32 {
|
||||
if is_3d_target(src_target) {
|
||||
//TODO: handle GLES without framebuffer_texture_3d
|
||||
gl.framebuffer_texture_layer(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
Some(src),
|
||||
copy.src_base.mip_level as i32,
|
||||
copy.src_base.origin.z as i32 + layer,
|
||||
);
|
||||
} else {
|
||||
gl.framebuffer_texture_2d(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
src_target,
|
||||
Some(src),
|
||||
copy.src_base.mip_level as i32,
|
||||
);
|
||||
}
|
||||
gl.bind_texture(dst_target, Some(dst));
|
||||
if is_3d_target(dst_target) {
|
||||
gl.copy_tex_sub_image_3d(
|
||||
dst_target,
|
||||
copy.dst_base.mip_level as i32,
|
||||
copy.dst_base.origin.x as i32,
|
||||
copy.dst_base.origin.y as i32,
|
||||
copy.dst_base.origin.z as i32 + layer,
|
||||
copy.src_base.origin.x as i32,
|
||||
copy.src_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
);
|
||||
} else {
|
||||
gl.copy_tex_sub_image_2d(
|
||||
dst_target,
|
||||
copy.dst_base.mip_level as i32,
|
||||
copy.dst_base.origin.x as i32,
|
||||
copy.dst_base.origin.y as i32,
|
||||
copy.src_base.origin.x as i32,
|
||||
copy.src_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
);
|
||||
}
|
||||
if is_3d_target(src_target) {
|
||||
//TODO: handle GLES without framebuffer_texture_3d
|
||||
gl.framebuffer_texture_layer(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
Some(src),
|
||||
copy.src_base.mip_level as i32,
|
||||
copy.src_base.array_layer as i32,
|
||||
);
|
||||
} else {
|
||||
gl.framebuffer_texture_2d(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
src_target,
|
||||
Some(src),
|
||||
copy.src_base.mip_level as i32,
|
||||
);
|
||||
}
|
||||
|
||||
gl.bind_texture(dst_target, Some(dst));
|
||||
if is_3d_target(dst_target) {
|
||||
gl.copy_tex_sub_image_3d(
|
||||
dst_target,
|
||||
copy.dst_base.mip_level as i32,
|
||||
copy.dst_base.origin.x as i32,
|
||||
copy.dst_base.origin.y as i32,
|
||||
copy.dst_base.origin.z as i32,
|
||||
copy.src_base.origin.x as i32,
|
||||
copy.src_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
);
|
||||
} else {
|
||||
gl.copy_tex_sub_image_2d(
|
||||
dst_target,
|
||||
copy.dst_base.mip_level as i32,
|
||||
copy.dst_base.origin.x as i32,
|
||||
copy.dst_base.origin.y as i32,
|
||||
copy.src_base.origin.x as i32,
|
||||
copy.src_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
);
|
||||
}
|
||||
}
|
||||
C::CopyBufferToTexture {
|
||||
@ -286,7 +285,7 @@ impl super::Queue {
|
||||
copy.texture_base.origin.z as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
copy.size.depth_or_array_layers as i32,
|
||||
copy.size.depth as i32,
|
||||
format_desc.external,
|
||||
format_desc.data_type,
|
||||
unpack_data,
|
||||
@ -306,26 +305,18 @@ impl super::Queue {
|
||||
);
|
||||
}
|
||||
glow::TEXTURE_CUBE_MAP => {
|
||||
let mut offset = copy.buffer_layout.offset as u32;
|
||||
for face_index in 0..copy.size.depth_or_array_layers {
|
||||
gl.tex_sub_image_2d(
|
||||
CUBEMAP_FACES
|
||||
[(copy.texture_base.origin.z + face_index) as usize],
|
||||
copy.texture_base.mip_level as i32,
|
||||
copy.texture_base.origin.x as i32,
|
||||
copy.texture_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
format_desc.external,
|
||||
format_desc.data_type,
|
||||
glow::PixelUnpackData::BufferOffset(offset),
|
||||
);
|
||||
offset += copy
|
||||
.buffer_layout
|
||||
.rows_per_image
|
||||
.map_or(0, |rpi| rpi.get())
|
||||
* copy.buffer_layout.bytes_per_row.map_or(0, |bpr| bpr.get());
|
||||
}
|
||||
let offset = copy.buffer_layout.offset as u32;
|
||||
gl.tex_sub_image_2d(
|
||||
CUBEMAP_FACES[copy.texture_base.array_layer as usize],
|
||||
copy.texture_base.mip_level as i32,
|
||||
copy.texture_base.origin.x as i32,
|
||||
copy.texture_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
format_desc.external,
|
||||
format_desc.data_type,
|
||||
glow::PixelUnpackData::BufferOffset(offset),
|
||||
);
|
||||
}
|
||||
glow::TEXTURE_CUBE_MAP_ARRAY => {
|
||||
//Note: not sure if this is correct!
|
||||
@ -337,7 +328,7 @@ impl super::Queue {
|
||||
copy.texture_base.origin.z as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
copy.size.depth_or_array_layers as i32,
|
||||
copy.size.depth as i32,
|
||||
format_desc.external,
|
||||
format_desc.data_type,
|
||||
unpack_data,
|
||||
@ -349,10 +340,9 @@ impl super::Queue {
|
||||
let bytes_per_image =
|
||||
copy.buffer_layout.rows_per_image.map_or(1, |rpi| rpi.get())
|
||||
* copy.buffer_layout.bytes_per_row.map_or(1, |bpr| bpr.get());
|
||||
let offset_end = copy.buffer_layout.offset as u32
|
||||
+ bytes_per_image * copy.size.depth_or_array_layers;
|
||||
let offset = copy.buffer_layout.offset as u32;
|
||||
let unpack_data = glow::CompressedPixelUnpackData::BufferRange(
|
||||
copy.buffer_layout.offset as u32..offset_end,
|
||||
offset..offset + bytes_per_image,
|
||||
);
|
||||
match dst_target {
|
||||
glow::TEXTURE_3D | glow::TEXTURE_2D_ARRAY => {
|
||||
@ -364,7 +354,7 @@ impl super::Queue {
|
||||
copy.texture_base.origin.z as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
copy.size.depth_or_array_layers as i32,
|
||||
copy.size.depth as i32,
|
||||
format_desc.internal,
|
||||
unpack_data,
|
||||
);
|
||||
@ -382,23 +372,18 @@ impl super::Queue {
|
||||
);
|
||||
}
|
||||
glow::TEXTURE_CUBE_MAP => {
|
||||
let mut offset = copy.buffer_layout.offset as u32;
|
||||
for face_index in 0..copy.size.depth_or_array_layers {
|
||||
gl.compressed_tex_sub_image_2d(
|
||||
CUBEMAP_FACES
|
||||
[(copy.texture_base.origin.z + face_index) as usize],
|
||||
copy.texture_base.mip_level as i32,
|
||||
copy.texture_base.origin.x as i32,
|
||||
copy.texture_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
format_desc.internal,
|
||||
glow::CompressedPixelUnpackData::BufferRange(
|
||||
offset..offset + bytes_per_image,
|
||||
),
|
||||
);
|
||||
offset += bytes_per_image;
|
||||
}
|
||||
gl.compressed_tex_sub_image_2d(
|
||||
CUBEMAP_FACES[copy.texture_base.array_layer as usize],
|
||||
copy.texture_base.mip_level as i32,
|
||||
copy.texture_base.origin.x as i32,
|
||||
copy.texture_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
format_desc.internal,
|
||||
glow::CompressedPixelUnpackData::BufferRange(
|
||||
offset..offset + bytes_per_image,
|
||||
),
|
||||
);
|
||||
}
|
||||
glow::TEXTURE_CUBE_MAP_ARRAY => {
|
||||
//Note: not sure if this is correct!
|
||||
@ -410,7 +395,7 @@ impl super::Queue {
|
||||
copy.texture_base.origin.z as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
copy.size.depth_or_array_layers as i32,
|
||||
copy.size.depth as i32,
|
||||
format_desc.internal,
|
||||
unpack_data,
|
||||
);
|
||||
@ -445,45 +430,37 @@ impl super::Queue {
|
||||
.map_or(copy.size.width, |bpr| {
|
||||
bpr.get() / format_info.block_size as u32
|
||||
});
|
||||
let column_texels = copy
|
||||
.buffer_layout
|
||||
.rows_per_image
|
||||
.map_or(copy.size.height, |rpi| rpi.get());
|
||||
gl.pixel_store_i32(glow::PACK_ROW_LENGTH, row_texels as i32);
|
||||
gl.bind_buffer(glow::PIXEL_PACK_BUFFER, Some(dst));
|
||||
|
||||
gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(self.copy_fbo));
|
||||
for layer in 0..copy.size.depth_or_array_layers {
|
||||
let offset = copy.buffer_layout.offset as u32
|
||||
+ layer * column_texels * row_texels * format_info.block_size as u32;
|
||||
if is_3d_target(src_target) {
|
||||
//TODO: handle GLES without framebuffer_texture_3d
|
||||
gl.framebuffer_texture_layer(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
Some(src),
|
||||
copy.texture_base.mip_level as i32,
|
||||
copy.texture_base.origin.z as i32 + layer as i32,
|
||||
);
|
||||
} else {
|
||||
gl.framebuffer_texture_2d(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
src_target,
|
||||
Some(src),
|
||||
copy.texture_base.mip_level as i32,
|
||||
);
|
||||
}
|
||||
gl.read_pixels(
|
||||
copy.texture_base.origin.x as i32,
|
||||
copy.texture_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
format_desc.external,
|
||||
format_desc.data_type,
|
||||
glow::PixelPackData::BufferOffset(offset),
|
||||
if is_3d_target(src_target) {
|
||||
//TODO: handle GLES without framebuffer_texture_3d
|
||||
gl.framebuffer_texture_layer(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
Some(src),
|
||||
copy.texture_base.mip_level as i32,
|
||||
copy.texture_base.array_layer as i32,
|
||||
);
|
||||
} else {
|
||||
gl.framebuffer_texture_2d(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
src_target,
|
||||
Some(src),
|
||||
copy.texture_base.mip_level as i32,
|
||||
);
|
||||
}
|
||||
gl.read_pixels(
|
||||
copy.texture_base.origin.x as i32,
|
||||
copy.texture_base.origin.y as i32,
|
||||
copy.size.width as i32,
|
||||
copy.size.height as i32,
|
||||
format_desc.external,
|
||||
format_desc.data_type,
|
||||
glow::PixelPackData::BufferOffset(copy.buffer_layout.offset as u32),
|
||||
);
|
||||
}
|
||||
C::SetIndexBuffer(buffer) => {
|
||||
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(buffer));
|
||||
|
@ -351,6 +351,8 @@ pub trait CommandEncoder<A: Api>: Send + Sync {
|
||||
where
|
||||
T: Iterator<Item = BufferCopy>;
|
||||
|
||||
/// Copy from one texture to another.
|
||||
/// Works with a single array layer.
|
||||
/// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
|
||||
unsafe fn copy_texture_to_texture<T>(
|
||||
&mut self,
|
||||
@ -361,11 +363,15 @@ pub trait CommandEncoder<A: Api>: Send + Sync {
|
||||
) where
|
||||
T: Iterator<Item = TextureCopy>;
|
||||
|
||||
/// Copy from buffer to texture.
|
||||
/// Works with a single array layer.
|
||||
/// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
|
||||
unsafe fn copy_buffer_to_texture<T>(&mut self, src: &A::Buffer, dst: &A::Texture, regions: T)
|
||||
where
|
||||
T: Iterator<Item = BufferTextureCopy>;
|
||||
|
||||
/// Copy from texture to buffer.
|
||||
/// Works with a single array layer.
|
||||
unsafe fn copy_texture_to_buffer<T>(
|
||||
&mut self,
|
||||
src: &A::Texture,
|
||||
@ -1006,26 +1012,33 @@ pub struct BufferCopy {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TextureCopyBase {
|
||||
pub origin: wgt::Origin3d,
|
||||
pub mip_level: u32,
|
||||
pub array_layer: u32,
|
||||
/// Origin within a texture.
|
||||
/// Note: for 1D and 2D textures, Z must be 0.
|
||||
pub origin: wgt::Origin3d,
|
||||
pub aspect: FormatAspects,
|
||||
}
|
||||
|
||||
//TODO: all the copy operations really want to separate
|
||||
// array layers from Z, so this should not use `wgt::Extent3d`,
|
||||
// and potentially work with a single layer at a time.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct CopyExtent {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub depth: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TextureCopy {
|
||||
pub src_base: TextureCopyBase,
|
||||
pub dst_base: TextureCopyBase,
|
||||
pub size: wgt::Extent3d,
|
||||
pub size: CopyExtent,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BufferTextureCopy {
|
||||
pub buffer_layout: wgt::ImageDataLayout,
|
||||
pub texture_base: TextureCopyBase,
|
||||
pub size: wgt::Extent3d,
|
||||
pub size: CopyExtent,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -156,22 +156,20 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
{
|
||||
let encoder = self.enter_blit();
|
||||
for copy in regions {
|
||||
let (src_slice, src_origin) = conv::map_origin(©.src_base.origin, src.raw_type);
|
||||
let (dst_slice, dst_origin) = conv::map_origin(©.dst_base.origin, dst.raw_type);
|
||||
let (slice_count, extent) = conv::map_extent(©.size, src.raw_type);
|
||||
for slice in 0..slice_count {
|
||||
encoder.copy_from_texture(
|
||||
&src.raw,
|
||||
src_slice + slice,
|
||||
copy.src_base.mip_level as u64,
|
||||
src_origin,
|
||||
extent,
|
||||
&dst.raw,
|
||||
dst_slice + slice,
|
||||
copy.dst_base.mip_level as u64,
|
||||
dst_origin,
|
||||
);
|
||||
}
|
||||
let src_origin = conv::map_origin(©.src_base.origin);
|
||||
let dst_origin = conv::map_origin(©.dst_base.origin);
|
||||
let extent = conv::map_copy_extent(©.size);
|
||||
encoder.copy_from_texture(
|
||||
&src.raw,
|
||||
copy.src_base.array_layer as u64,
|
||||
copy.src_base.mip_level as u64,
|
||||
src_origin,
|
||||
extent,
|
||||
&dst.raw,
|
||||
copy.dst_base.array_layer as u64,
|
||||
copy.dst_base.mip_level as u64,
|
||||
dst_origin,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,8 +183,8 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
{
|
||||
let encoder = self.enter_blit();
|
||||
for copy in regions {
|
||||
let (dst_slice, dst_origin) = conv::map_origin(©.texture_base.origin, dst.raw_type);
|
||||
let (slice_count, extent) = conv::map_extent(©.size, dst.raw_type);
|
||||
let dst_origin = conv::map_origin(©.texture_base.origin);
|
||||
let extent = conv::map_copy_extent(©.size);
|
||||
let bytes_per_row = copy
|
||||
.buffer_layout
|
||||
.bytes_per_row
|
||||
@ -195,21 +193,18 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
.buffer_layout
|
||||
.rows_per_image
|
||||
.map_or(0, |v| v.get() as u64 * bytes_per_row);
|
||||
for slice in 0..slice_count {
|
||||
let offset = copy.buffer_layout.offset + bytes_per_image * slice;
|
||||
encoder.copy_from_buffer_to_texture(
|
||||
&src.raw,
|
||||
offset,
|
||||
bytes_per_row,
|
||||
bytes_per_image,
|
||||
extent,
|
||||
&dst.raw,
|
||||
dst_slice + slice,
|
||||
copy.texture_base.mip_level as u64,
|
||||
dst_origin,
|
||||
mtl::MTLBlitOption::empty(),
|
||||
);
|
||||
}
|
||||
encoder.copy_from_buffer_to_texture(
|
||||
&src.raw,
|
||||
copy.buffer_layout.offset,
|
||||
bytes_per_row,
|
||||
bytes_per_image,
|
||||
extent,
|
||||
&dst.raw,
|
||||
copy.texture_base.array_layer as u64,
|
||||
copy.texture_base.mip_level as u64,
|
||||
dst_origin,
|
||||
mtl::MTLBlitOption::empty(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,8 +219,8 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
{
|
||||
let encoder = self.enter_blit();
|
||||
for copy in regions {
|
||||
let (src_slice, src_origin) = conv::map_origin(©.texture_base.origin, src.raw_type);
|
||||
let (slice_count, extent) = conv::map_extent(©.size, src.raw_type);
|
||||
let src_origin = conv::map_origin(©.texture_base.origin);
|
||||
let extent = conv::map_copy_extent(©.size);
|
||||
let bytes_per_row = copy
|
||||
.buffer_layout
|
||||
.bytes_per_row
|
||||
@ -234,21 +229,18 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
.buffer_layout
|
||||
.rows_per_image
|
||||
.map_or(0, |v| v.get() as u64 * bytes_per_row);
|
||||
for slice in 0..slice_count {
|
||||
let offset = copy.buffer_layout.offset + bytes_per_image * slice;
|
||||
encoder.copy_from_texture_to_buffer(
|
||||
&src.raw,
|
||||
src_slice + slice,
|
||||
copy.texture_base.mip_level as u64,
|
||||
src_origin,
|
||||
extent,
|
||||
&dst.raw,
|
||||
offset,
|
||||
bytes_per_row,
|
||||
bytes_per_image,
|
||||
mtl::MTLBlitOption::empty(),
|
||||
);
|
||||
}
|
||||
encoder.copy_from_texture_to_buffer(
|
||||
&src.raw,
|
||||
copy.texture_base.array_layer as u64,
|
||||
copy.texture_base.mip_level as u64,
|
||||
src_origin,
|
||||
extent,
|
||||
&dst.raw,
|
||||
copy.buffer_layout.offset,
|
||||
bytes_per_row,
|
||||
bytes_per_image,
|
||||
mtl::MTLBlitOption::empty(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,34 +261,20 @@ pub fn map_range(range: &crate::MemoryRange) -> mtl::NSRange {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_extent(extent: &wgt::Extent3d, raw_type: mtl::MTLTextureType) -> (u64, mtl::MTLSize) {
|
||||
let (depth, array_layers) = match raw_type {
|
||||
mtl::MTLTextureType::D3 => (extent.depth_or_array_layers as u64, 1),
|
||||
_ => (1, extent.depth_or_array_layers as u64),
|
||||
};
|
||||
(
|
||||
array_layers,
|
||||
mtl::MTLSize {
|
||||
width: extent.width as u64,
|
||||
height: extent.height as u64,
|
||||
depth,
|
||||
},
|
||||
)
|
||||
pub fn map_copy_extent(extent: &crate::CopyExtent) -> mtl::MTLSize {
|
||||
mtl::MTLSize {
|
||||
width: extent.width as u64,
|
||||
height: extent.height as u64,
|
||||
depth: extent.depth as u64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_origin(origin: &wgt::Origin3d, raw_type: mtl::MTLTextureType) -> (u64, mtl::MTLOrigin) {
|
||||
let (z, slice) = match raw_type {
|
||||
mtl::MTLTextureType::D3 => (origin.z as u64, 0),
|
||||
_ => (0, origin.z as u64),
|
||||
};
|
||||
(
|
||||
slice,
|
||||
mtl::MTLOrigin {
|
||||
x: origin.x as u64,
|
||||
y: origin.y as u64,
|
||||
z,
|
||||
},
|
||||
)
|
||||
pub fn map_origin(origin: &wgt::Origin3d) -> mtl::MTLOrigin {
|
||||
mtl::MTLOrigin {
|
||||
x: origin.x as u64,
|
||||
y: origin.y as u64,
|
||||
z: origin.z as u64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_store_action(store: bool, resolve: bool) -> mtl::MTLStoreAction {
|
||||
|
@ -18,13 +18,11 @@ impl super::Texture {
|
||||
where
|
||||
T: Iterator<Item = crate::BufferTextureCopy>,
|
||||
{
|
||||
let dim = self.dim;
|
||||
let aspects = self.aspects;
|
||||
let fi = self.format_info;
|
||||
regions.map(move |r| {
|
||||
let (layer_count, image_extent) = conv::map_extent(r.size, dim);
|
||||
let (image_subresource, image_offset) =
|
||||
conv::map_subresource_layers(&r.texture_base, dim, aspects, layer_count);
|
||||
conv::map_subresource_layers(&r.texture_base, aspects);
|
||||
vk::BufferImageCopy {
|
||||
buffer_offset: r.buffer_layout.offset,
|
||||
buffer_row_length: r.buffer_layout.bytes_per_row.map_or(0, |bpr| {
|
||||
@ -36,7 +34,7 @@ impl super::Texture {
|
||||
.map_or(0, |rpi| rpi.get() * fi.block_dimensions.1 as u32),
|
||||
image_subresource,
|
||||
image_offset,
|
||||
image_extent,
|
||||
image_extent: conv::map_copy_extent(&r.size),
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -228,17 +226,16 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
let src_layout = conv::derive_image_layout(src_usage, src.aspects);
|
||||
|
||||
let vk_regions_iter = regions.map(|r| {
|
||||
let (layer_count, extent) = conv::map_extent(r.size, src.dim);
|
||||
let (src_subresource, src_offset) =
|
||||
conv::map_subresource_layers(&r.src_base, src.dim, src.aspects, layer_count);
|
||||
conv::map_subresource_layers(&r.src_base, src.aspects);
|
||||
let (dst_subresource, dst_offset) =
|
||||
conv::map_subresource_layers(&r.dst_base, dst.dim, dst.aspects, layer_count);
|
||||
conv::map_subresource_layers(&r.dst_base, dst.aspects);
|
||||
vk::ImageCopy {
|
||||
src_subresource,
|
||||
src_offset,
|
||||
dst_subresource,
|
||||
dst_offset,
|
||||
extent,
|
||||
extent: conv::map_copy_extent(&r.size),
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -352,42 +352,6 @@ pub fn map_aspects(aspects: crate::FormatAspects) -> vk::ImageAspectFlags {
|
||||
flags
|
||||
}
|
||||
|
||||
pub fn map_origin(
|
||||
origin: wgt::Origin3d,
|
||||
texture_dim: wgt::TextureDimension,
|
||||
) -> (u32, vk::Offset3D) {
|
||||
let (z, array_layer) = match texture_dim {
|
||||
wgt::TextureDimension::D3 => (origin.z as i32, 0),
|
||||
_ => (0, origin.z),
|
||||
};
|
||||
(
|
||||
array_layer,
|
||||
vk::Offset3D {
|
||||
x: origin.x as i32,
|
||||
y: origin.y as i32,
|
||||
z,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn map_extent(
|
||||
extent: wgt::Extent3d,
|
||||
texture_dim: wgt::TextureDimension,
|
||||
) -> (u32, vk::Extent3D) {
|
||||
let (depth, array_layers) = match texture_dim {
|
||||
wgt::TextureDimension::D3 => (extent.depth_or_array_layers, 1),
|
||||
_ => (1, extent.depth_or_array_layers),
|
||||
};
|
||||
(
|
||||
array_layers,
|
||||
vk::Extent3D {
|
||||
width: extent.width,
|
||||
height: extent.height,
|
||||
depth,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn map_attachment_ops(
|
||||
op: crate::AttachmentOps,
|
||||
) -> (vk::AttachmentLoadOp, vk::AttachmentStoreOp) {
|
||||
@ -541,6 +505,14 @@ pub fn map_view_dimension(dim: wgt::TextureViewDimension) -> vk::ImageViewType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_copy_extent(extent: &crate::CopyExtent) -> vk::Extent3D {
|
||||
vk::Extent3D {
|
||||
width: extent.width,
|
||||
height: extent.height,
|
||||
depth: extent.depth,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_subresource_range(
|
||||
range: &wgt::ImageSubresourceRange,
|
||||
texture_aspect: crate::FormatAspects,
|
||||
@ -560,16 +532,18 @@ pub fn map_subresource_range(
|
||||
|
||||
pub fn map_subresource_layers(
|
||||
base: &crate::TextureCopyBase,
|
||||
texture_dim: wgt::TextureDimension,
|
||||
texture_aspect: crate::FormatAspects,
|
||||
layer_count: u32,
|
||||
) -> (vk::ImageSubresourceLayers, vk::Offset3D) {
|
||||
let (base_array_layer, offset) = map_origin(base.origin, texture_dim);
|
||||
let offset = vk::Offset3D {
|
||||
x: base.origin.x as i32,
|
||||
y: base.origin.y as i32,
|
||||
z: base.origin.z as i32,
|
||||
};
|
||||
let subresource = vk::ImageSubresourceLayers {
|
||||
aspect_mask: map_aspects(base.aspect & texture_aspect),
|
||||
mip_level: base.mip_level,
|
||||
base_array_layer,
|
||||
layer_count,
|
||||
base_array_layer: base.array_layer,
|
||||
layer_count: 1,
|
||||
};
|
||||
(subresource, offset)
|
||||
}
|
||||
|
@ -654,7 +654,11 @@ impl crate::Device<super::Api> for super::Device {
|
||||
&self,
|
||||
desc: &crate::TextureDescriptor,
|
||||
) -> Result<super::Texture, crate::DeviceError> {
|
||||
let (array_layer_count, vk_extent) = conv::map_extent(desc.size, desc.dimension);
|
||||
let (depth, array_layer_count) = match desc.dimension {
|
||||
wgt::TextureDimension::D3 => (desc.size.depth_or_array_layers, 1),
|
||||
_ => (1, desc.size.depth_or_array_layers),
|
||||
};
|
||||
|
||||
let mut raw_flags = vk::ImageCreateFlags::empty();
|
||||
if desc.dimension == wgt::TextureDimension::D2 && desc.size.depth_or_array_layers % 6 == 0 {
|
||||
raw_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
|
||||
@ -664,7 +668,11 @@ impl crate::Device<super::Api> for super::Device {
|
||||
.flags(raw_flags)
|
||||
.image_type(conv::map_texture_dimension(desc.dimension))
|
||||
.format(self.shared.private_caps.map_texture_format(desc.format))
|
||||
.extent(vk_extent)
|
||||
.extent(vk::Extent3D {
|
||||
width: desc.size.width,
|
||||
height: desc.size.height,
|
||||
depth,
|
||||
})
|
||||
.mip_levels(desc.mip_level_count)
|
||||
.array_layers(array_layer_count)
|
||||
.samples(vk::SampleCountFlags::from_raw(desc.sample_count))
|
||||
@ -699,7 +707,6 @@ impl crate::Device<super::Api> for super::Device {
|
||||
raw,
|
||||
block: Some(block),
|
||||
usage: desc.usage,
|
||||
dim: desc.dimension,
|
||||
aspects: crate::FormatAspects::from(desc.format),
|
||||
format_info: desc.format.describe(),
|
||||
raw_flags,
|
||||
|
@ -647,7 +647,6 @@ impl crate::Surface<super::Api> for super::Surface {
|
||||
raw: sc.images[index as usize],
|
||||
block: None,
|
||||
usage: sc.config.usage,
|
||||
dim: wgt::TextureDimension::D2,
|
||||
aspects: crate::FormatAspects::COLOR,
|
||||
format_info: sc.config.format.describe(),
|
||||
raw_flags: vk::ImageCreateFlags::empty(),
|
||||
|
@ -255,7 +255,6 @@ pub struct Texture {
|
||||
raw: vk::Image,
|
||||
block: Option<gpu_alloc::MemoryBlock<vk::DeviceMemory>>,
|
||||
usage: crate::TextureUses,
|
||||
dim: wgt::TextureDimension,
|
||||
aspects: crate::FormatAspects,
|
||||
format_info: wgt::TextureFormatInfo,
|
||||
raw_flags: vk::ImageCreateFlags,
|
||||
|
Loading…
Reference in New Issue
Block a user