mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
Add DownlevelFlag to prevent copies between Depth32 Textures
This commit is contained in:
parent
3623f5020d
commit
b61939650c
@ -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(
|
||||
|
@ -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 {}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user