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
76c7161364
commit
72cb3d0124
@ -105,7 +105,7 @@ impl LodData {
|
||||
array_layer_count: None,
|
||||
};
|
||||
|
||||
renderer.create_texture_with_data_raw::<4>(
|
||||
renderer.create_texture_with_data_raw(
|
||||
&texture_info,
|
||||
&view_info,
|
||||
&sampler_info,
|
||||
|
@ -116,7 +116,7 @@ pub fn create_col_lights(
|
||||
array_layer_count: None,
|
||||
};
|
||||
|
||||
renderer.create_texture_with_data_raw::<4>(
|
||||
renderer.create_texture_with_data_raw(
|
||||
&texture_info,
|
||||
&view_info,
|
||||
&sampler_info,
|
||||
|
@ -1094,7 +1094,10 @@ impl Renderer {
|
||||
}
|
||||
|
||||
/// 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,
|
||||
texture_info: &wgpu::TextureDescriptor,
|
||||
view_info: &wgpu::TextureViewDescriptor,
|
||||
@ -1103,7 +1106,20 @@ impl Renderer {
|
||||
) -> Texture {
|
||||
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.queue,
|
||||
[0; 2],
|
||||
@ -1121,7 +1137,9 @@ impl Renderer {
|
||||
view_info: &wgpu::TextureViewDescriptor,
|
||||
sampler_info: &wgpu::SamplerDescriptor,
|
||||
) -> 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.
|
||||
@ -1147,7 +1165,7 @@ impl Renderer {
|
||||
///
|
||||
/// Currently only supports Rgba8Srgb
|
||||
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.
|
||||
@ -1158,18 +1176,10 @@ impl Renderer {
|
||||
texture: &Texture, /* <T> */
|
||||
offset: [u32; 2],
|
||||
size: [u32; 2],
|
||||
// TODO
|
||||
// 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)
|
||||
// TODO: generic over pixel type
|
||||
data: &[[u8; 4]],
|
||||
) {
|
||||
texture.update::<4>(
|
||||
texture.update(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
offset,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::RenderError;
|
||||
use core::num::NonZeroU32;
|
||||
use image::{DynamicImage, GenericImageView};
|
||||
use wgpu::Extent3d;
|
||||
use core::num::NonZeroU32;
|
||||
|
||||
/// Represents an image that has been uploaded to the GPU.
|
||||
pub struct Texture {
|
||||
@ -9,6 +9,8 @@ pub struct Texture {
|
||||
pub view: wgpu::TextureView,
|
||||
pub sampler: wgpu::Sampler,
|
||||
size: Extent3d,
|
||||
/// TODO: consider making Texture generic over the format
|
||||
format: wgpu::TextureFormat,
|
||||
}
|
||||
|
||||
impl Texture {
|
||||
@ -106,10 +108,16 @@ impl Texture {
|
||||
view,
|
||||
sampler: device.create_sampler(&sampler_info),
|
||||
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 {
|
||||
width,
|
||||
height,
|
||||
@ -149,9 +157,13 @@ impl Texture {
|
||||
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(
|
||||
device: &wgpu::Device,
|
||||
texture_info: &wgpu::TextureDescriptor,
|
||||
@ -166,14 +178,25 @@ impl Texture {
|
||||
view,
|
||||
sampler: device.create_sampler(sampler_info),
|
||||
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
|
||||
/// texture).
|
||||
/// TODO: using generic here seems a bit hacky, consider storing this info
|
||||
/// in the texture type or pass in wgpu::TextureFormat
|
||||
pub fn update<const BYTES_PER_PIXEL: u32>(
|
||||
pub fn update(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
@ -181,9 +204,11 @@ impl Texture {
|
||||
size: [u32; 2],
|
||||
data: &[u8],
|
||||
) {
|
||||
let bytes_per_pixel = self.format.describe().block_size as u32;
|
||||
|
||||
debug_assert_eq!(
|
||||
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
|
||||
queue.write_texture(
|
||||
@ -199,7 +224,7 @@ impl Texture {
|
||||
data,
|
||||
wgpu::ImageDataLayout {
|
||||
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]),
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
|
Loading…
Reference in New Issue
Block a user