mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Clear textures that will be partially written to work around Dx12 bug on AMD
This commit is contained in:
parent
1fb52be531
commit
579e032f40
@ -105,7 +105,7 @@ impl LodData {
|
|||||||
array_layer_count: None,
|
array_layer_count: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
renderer.create_texture_with_data_raw::<4>(
|
renderer.create_texture_with_data_raw(
|
||||||
&texture_info,
|
&texture_info,
|
||||||
&view_info,
|
&view_info,
|
||||||
&sampler_info,
|
&sampler_info,
|
||||||
|
@ -116,7 +116,7 @@ pub fn create_col_lights(
|
|||||||
array_layer_count: None,
|
array_layer_count: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
renderer.create_texture_with_data_raw::<4>(
|
renderer.create_texture_with_data_raw(
|
||||||
&texture_info,
|
&texture_info,
|
||||||
&view_info,
|
&view_info,
|
||||||
&sampler_info,
|
&sampler_info,
|
||||||
|
@ -1094,7 +1094,10 @@ impl Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new immutable texture from the provided image.
|
/// Create a new immutable texture from the provided image.
|
||||||
pub fn create_texture_with_data_raw<const BYTES_PER_PIXEL: u32>(
|
/// # Panics
|
||||||
|
/// If the provided data doesn't completely fill the texture this function
|
||||||
|
/// will panic.
|
||||||
|
pub fn create_texture_with_data_raw(
|
||||||
&mut self,
|
&mut self,
|
||||||
texture_info: &wgpu::TextureDescriptor,
|
texture_info: &wgpu::TextureDescriptor,
|
||||||
view_info: &wgpu::TextureViewDescriptor,
|
view_info: &wgpu::TextureViewDescriptor,
|
||||||
@ -1103,7 +1106,20 @@ impl Renderer {
|
|||||||
) -> Texture {
|
) -> Texture {
|
||||||
let tex = Texture::new_raw(&self.device, &texture_info, &view_info, &sampler_info);
|
let tex = Texture::new_raw(&self.device, &texture_info, &view_info, &sampler_info);
|
||||||
|
|
||||||
tex.update::<BYTES_PER_PIXEL>(
|
let size = texture_info.size;
|
||||||
|
let block_size = texture_info.format.describe().block_size;
|
||||||
|
assert_eq!(
|
||||||
|
size.width as usize
|
||||||
|
* size.height as usize
|
||||||
|
* size.depth_or_array_layers as usize
|
||||||
|
* block_size as usize,
|
||||||
|
data.len(),
|
||||||
|
"Provided data length {} does not fill the provided texture size {:?}",
|
||||||
|
data.len(),
|
||||||
|
size,
|
||||||
|
);
|
||||||
|
|
||||||
|
tex.update(
|
||||||
&self.device,
|
&self.device,
|
||||||
&self.queue,
|
&self.queue,
|
||||||
[0; 2],
|
[0; 2],
|
||||||
@ -1121,7 +1137,9 @@ impl Renderer {
|
|||||||
view_info: &wgpu::TextureViewDescriptor,
|
view_info: &wgpu::TextureViewDescriptor,
|
||||||
sampler_info: &wgpu::SamplerDescriptor,
|
sampler_info: &wgpu::SamplerDescriptor,
|
||||||
) -> Texture {
|
) -> Texture {
|
||||||
Texture::new_raw(&self.device, texture_info, view_info, sampler_info)
|
let texture = Texture::new_raw(&self.device, texture_info, view_info, sampler_info);
|
||||||
|
texture.clear(&self.device, &self.queue); // Needs to be fully initialized for partial writes to work on Dx12 AMD
|
||||||
|
texture
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new texture from the provided image.
|
/// Create a new texture from the provided image.
|
||||||
@ -1147,7 +1165,7 @@ impl Renderer {
|
|||||||
///
|
///
|
||||||
/// Currently only supports Rgba8Srgb
|
/// Currently only supports Rgba8Srgb
|
||||||
pub fn create_dynamic_texture(&mut self, dims: Vec2<u32>) -> Texture {
|
pub fn create_dynamic_texture(&mut self, dims: Vec2<u32>) -> Texture {
|
||||||
Texture::new_dynamic(&self.device, dims.x, dims.y)
|
Texture::new_dynamic(&self.device, &self.queue, dims.x, dims.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update a texture with the provided offset, size, and data.
|
/// Update a texture with the provided offset, size, and data.
|
||||||
@ -1158,18 +1176,10 @@ impl Renderer {
|
|||||||
texture: &Texture, /* <T> */
|
texture: &Texture, /* <T> */
|
||||||
offset: [u32; 2],
|
offset: [u32; 2],
|
||||||
size: [u32; 2],
|
size: [u32; 2],
|
||||||
// TODO
|
// TODO: generic over pixel type
|
||||||
// data: &[<<T as gfx::format::Formatted>::Surface as
|
|
||||||
// gfx::format::SurfaceTyped>::DataType], ) -> Result<(), RenderError>
|
|
||||||
// where
|
|
||||||
// <T as gfx::format::Formatted>::Surface: gfx::format::TextureSurface,
|
|
||||||
// <T as gfx::format::Formatted>::Channel: gfx::format::TextureChannel,
|
|
||||||
// <<T as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType:
|
|
||||||
// Copy, {
|
|
||||||
// texture.update(&mut self.encoder, offset, size, data)
|
|
||||||
data: &[[u8; 4]],
|
data: &[[u8; 4]],
|
||||||
) {
|
) {
|
||||||
texture.update::<4>(
|
texture.update(
|
||||||
&self.device,
|
&self.device,
|
||||||
&self.queue,
|
&self.queue,
|
||||||
offset,
|
offset,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::RenderError;
|
use super::RenderError;
|
||||||
|
use core::num::NonZeroU32;
|
||||||
use image::{DynamicImage, GenericImageView};
|
use image::{DynamicImage, GenericImageView};
|
||||||
use wgpu::Extent3d;
|
use wgpu::Extent3d;
|
||||||
use core::num::NonZeroU32;
|
|
||||||
|
|
||||||
/// Represents an image that has been uploaded to the GPU.
|
/// Represents an image that has been uploaded to the GPU.
|
||||||
pub struct Texture {
|
pub struct Texture {
|
||||||
@ -9,6 +9,8 @@ pub struct Texture {
|
|||||||
pub view: wgpu::TextureView,
|
pub view: wgpu::TextureView,
|
||||||
pub sampler: wgpu::Sampler,
|
pub sampler: wgpu::Sampler,
|
||||||
size: Extent3d,
|
size: Extent3d,
|
||||||
|
/// TODO: consider making Texture generic over the format
|
||||||
|
format: wgpu::TextureFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Texture {
|
impl Texture {
|
||||||
@ -106,10 +108,16 @@ impl Texture {
|
|||||||
view,
|
view,
|
||||||
sampler: device.create_sampler(&sampler_info),
|
sampler: device.create_sampler(&sampler_info),
|
||||||
size,
|
size,
|
||||||
|
format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_dynamic(device: &wgpu::Device, width: u32, height: u32) -> Self {
|
pub fn new_dynamic(
|
||||||
|
device: &wgpu::Device,
|
||||||
|
queue: &wgpu::Queue,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) -> Self {
|
||||||
let size = wgpu::Extent3d {
|
let size = wgpu::Extent3d {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
@ -149,9 +157,13 @@ impl Texture {
|
|||||||
array_layer_count: None,
|
array_layer_count: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::new_raw(device, &tex_info, &view_info, &sampler_info)
|
let texture = Self::new_raw(device, &tex_info, &view_info, &sampler_info);
|
||||||
|
texture.clear(device, queue); // Needs to be fully initialized for partial writes to work on Dx12 AMD
|
||||||
|
texture
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Note: the user is responsible for making sure the texture is fully
|
||||||
|
/// initialized before doing partial writes on Dx12 AMD: https://github.com/gfx-rs/wgpu/issues/1306
|
||||||
pub fn new_raw(
|
pub fn new_raw(
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
texture_info: &wgpu::TextureDescriptor,
|
texture_info: &wgpu::TextureDescriptor,
|
||||||
@ -166,14 +178,25 @@ impl Texture {
|
|||||||
view,
|
view,
|
||||||
sampler: device.create_sampler(sampler_info),
|
sampler: device.create_sampler(sampler_info),
|
||||||
size: texture_info.size,
|
size: texture_info.size,
|
||||||
|
format: texture_info.format,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clears the texture data to 0
|
||||||
|
pub fn clear(&self, device: &wgpu::Device, queue: &wgpu::Queue) {
|
||||||
|
let size = self.size;
|
||||||
|
let byte_len = size.width as usize
|
||||||
|
* size.height as usize
|
||||||
|
* size.depth_or_array_layers as usize
|
||||||
|
* self.format.describe().block_size as usize;
|
||||||
|
let zeros = vec![0; byte_len];
|
||||||
|
|
||||||
|
self.update(device, queue, [0, 0], [size.width, size.height], &zeros);
|
||||||
|
}
|
||||||
|
|
||||||
/// Update a texture with the given data (used for updating the glyph cache
|
/// Update a texture with the given data (used for updating the glyph cache
|
||||||
/// texture).
|
/// texture).
|
||||||
/// TODO: using generic here seems a bit hacky, consider storing this info
|
pub fn update(
|
||||||
/// in the texture type or pass in wgpu::TextureFormat
|
|
||||||
pub fn update<const BYTES_PER_PIXEL: u32>(
|
|
||||||
&self,
|
&self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
queue: &wgpu::Queue,
|
||||||
@ -181,9 +204,11 @@ impl Texture {
|
|||||||
size: [u32; 2],
|
size: [u32; 2],
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) {
|
) {
|
||||||
|
let bytes_per_pixel = self.format.describe().block_size as u32;
|
||||||
|
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
data.len(),
|
data.len(),
|
||||||
size[0] as usize * size[1] as usize * BYTES_PER_PIXEL as usize
|
size[0] as usize * size[1] as usize * bytes_per_pixel as usize
|
||||||
);
|
);
|
||||||
// TODO: Only works for 2D images
|
// TODO: Only works for 2D images
|
||||||
queue.write_texture(
|
queue.write_texture(
|
||||||
@ -199,7 +224,7 @@ impl Texture {
|
|||||||
data,
|
data,
|
||||||
wgpu::ImageDataLayout {
|
wgpu::ImageDataLayout {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
bytes_per_row: NonZeroU32::new(size[0] * BYTES_PER_PIXEL),
|
bytes_per_row: NonZeroU32::new(size[0] * bytes_per_pixel),
|
||||||
rows_per_image: NonZeroU32::new(size[1]),
|
rows_per_image: NonZeroU32::new(size[1]),
|
||||||
},
|
},
|
||||||
wgpu::Extent3d {
|
wgpu::Extent3d {
|
||||||
|
Loading…
Reference in New Issue
Block a user