Add DownlevelFlag to prevent copies between Depth32 Textures

This commit is contained in:
Connor Fitzgerald 2022-02-23 23:56:16 -05:00 committed by Dzmitry Malyshau
parent 3623f5020d
commit b61939650c
7 changed files with 94 additions and 38 deletions

View File

@ -3,7 +3,7 @@ use crate::device::trace::Command as TraceCommand;
use crate::{
command::{CommandBuffer, CommandEncoderError},
conv,
device::Device,
device::{Device, MissingDownlevelFlags},
error::{ErrorFormatter, PrettyError},
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
id::{BufferId, CommandEncoderId, Id, TextureId, Valid},
@ -108,6 +108,8 @@ pub enum TransferError {
},
#[error(transparent)]
MemoryInitFailure(#[from] super::ClearError),
#[error("Cannot encode this copy because of a missing downelevel flag")]
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
}
impl PrettyError for TransferError {
@ -839,6 +841,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
);
}
if format_desc.sample_type == wgt::TextureSampleType::Depth
&& !device
.downlevel
.flags
.contains(wgt::DownlevelFlags::DEPTH_TEXTURE_AND_BUFFER_COPIES)
{
return Err(TransferError::MissingDownlevelFlags(MissingDownlevelFlags(
wgt::DownlevelFlags::DEPTH_TEXTURE_AND_BUFFER_COPIES,
))
.into());
}
cmd_buf
.buffer_memory_init_actions
.extend(dst_buffer.initialization_status.create_action(

View File

@ -359,6 +359,10 @@ impl super::Adapter {
super::PrivateCapabilities::CAN_DISABLE_DRAW_BUFFER,
!cfg!(target_arch = "wasm32"),
);
private_caps.set(
super::PrivateCapabilities::GET_BUFFER_SUB_DATA,
cfg!(target_arch = "wasm32"),
);
let max_texture_size = gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) as u32;
let max_texture_3d_size = gl.get_parameter_i32(glow::MAX_3D_TEXTURE_SIZE) as u32;
@ -706,6 +710,32 @@ impl crate::Adapter<super::Api> for super::Adapter {
}
}
impl super::AdapterShared {
pub(super) unsafe fn get_buffer_sub_data(
&self,
gl: &glow::Context,
target: u32,
offset: i32,
dst_data: &mut [u8],
) {
if self
.private_caps
.contains(super::PrivateCapabilities::GET_BUFFER_SUB_DATA)
{
gl.get_buffer_sub_data(target, offset, dst_data);
} else {
log::error!("Fake map");
let length = dst_data.len();
let buffer_mapping =
gl.map_buffer_range(target, offset, length as _, glow::MAP_READ_BIT);
std::ptr::copy_nonoverlapping(buffer_mapping, dst_data.as_mut_ptr(), length);
gl.unmap_buffer(target);
}
}
}
// SAFE: WASM doesn't have threads
#[cfg(target_arch = "wasm32")]
unsafe impl Sync for super::Adapter {}

View File

@ -457,7 +457,7 @@ impl crate::Device<super::Api> for super::Device {
let ptr = if let Some(ref map_read_allocation) = buffer.data {
let mut guard = map_read_allocation.lock().unwrap();
let slice = guard.as_mut_slice();
gl.get_buffer_sub_data(buffer.target, 0, slice);
self.shared.get_buffer_sub_data(gl, buffer.target, 0, slice);
slice.as_mut_ptr()
} else {
gl.map_buffer_range(
@ -478,11 +478,7 @@ impl crate::Device<super::Api> for super::Device {
}
unsafe fn unmap_buffer(&self, buffer: &super::Buffer) -> Result<(), crate::DeviceError> {
if let Some(raw) = buffer.raw {
if !self
.shared
.workarounds
.contains(super::Workarounds::EMULATE_BUFFER_MAP)
{
if buffer.data.is_none() {
let gl = &self.shared.context.lock();
gl.bind_buffer(buffer.target, Some(raw));
gl.unmap_buffer(buffer.target);

View File

@ -135,6 +135,8 @@ bitflags::bitflags! {
const INDEX_BUFFER_ROLE_CHANGE = 1 << 5;
/// Indicates that the device supports disabling draw buffers
const CAN_DISABLE_DRAW_BUFFER = 1 << 6;
/// Supports `glGetBufferSubData`
const GET_BUFFER_SUB_DATA = 1 << 7;
}
}

View File

@ -274,7 +274,12 @@ impl super::Queue {
[copy.dst_offset as usize..copy.dst_offset as usize + size];
gl.bind_buffer(copy_src_target, Some(src));
gl.get_buffer_sub_data(copy_src_target, copy.src_offset as i32, dst_data);
self.shared.get_buffer_sub_data(
gl,
copy_src_target,
copy.src_offset as i32,
dst_data,
);
}
(None, Some(dst)) => {
let data = src.data.as_ref().unwrap().lock().unwrap();

View File

@ -991,6 +991,10 @@ bitflags::bitflags! {
/// Supports sample-rate shading.
const MULTISAMPLED_SHADING = 1 << 12;
/// Supports copies between depth textures and buffers.
///
/// GLES/WebGL don't support this.
const DEPTH_TEXTURE_AND_BUFFER_COPIES = 1 << 13;
}
}

View File

@ -68,38 +68,43 @@ fn discarding_color_target_resets_texture_init_state_check_visible_on_copy_in_sa
#[test]
fn discarding_depth_target_resets_texture_init_state_check_visible_on_copy_in_same_encoder() {
initialize_test(TestParameters::default(), |ctx| {
for format in [
wgpu::TextureFormat::Depth32Float,
//wgpu::TextureFormat::Depth24Plus, // Can't copy to or from buffer
//wgpu::TextureFormat::Depth24PlusStencil8, // Can only copy stencil aspect to/from buffer
] {
let (texture, readback_buffer) = create_white_texture_and_readback_buffer(&ctx, format);
{
let mut encoder = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Depth Discard"),
color_attachments: &[],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
view: &texture.create_view(&wgpu::TextureViewDescriptor::default()),
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Load,
store: false, // discard!
initialize_test(
TestParameters::default()
.downlevel_flags(wgpu::DownlevelFlags::DEPTH_TEXTURE_AND_BUFFER_COPIES),
|ctx| {
for format in [
wgpu::TextureFormat::Depth32Float,
//wgpu::TextureFormat::Depth24Plus, // Can't copy to or from buffer
//wgpu::TextureFormat::Depth24PlusStencil8, // Can only copy stencil aspect to/from buffer
] {
let (texture, readback_buffer) =
create_white_texture_and_readback_buffer(&ctx, format);
{
let mut encoder = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Depth Discard"),
color_attachments: &[],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
view: &texture.create_view(&wgpu::TextureViewDescriptor::default()),
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Load,
store: false, // discard!
}),
stencil_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Load,
store: false, // discard!
}),
}),
stencil_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Load,
store: false, // discard!
}),
}),
});
copy_texture_to_buffer(&mut encoder, &texture, &readback_buffer);
ctx.queue.submit([encoder.finish()]);
});
copy_texture_to_buffer(&mut encoder, &texture, &readback_buffer);
ctx.queue.submit([encoder.finish()]);
}
assert_buffer_is_zero(&readback_buffer, &ctx.device);
}
assert_buffer_is_zero(&readback_buffer, &ctx.device);
}
});
},
);
}
#[test]