refactor project structure (start of redoing atomic branch without atomics)
This commit is contained in:
129
core/src/render/texture.rs
Normal file
129
core/src/render/texture.rs
Normal file
@@ -0,0 +1,129 @@
|
||||
use image::{DynamicImage, EncodableLayout};
|
||||
use wgpu::{util::DeviceExt, *};
|
||||
|
||||
use crate::layout::{TextureUpdate, Textures};
|
||||
|
||||
pub struct GpuTextures {
|
||||
device: Device,
|
||||
queue: Queue,
|
||||
views: Vec<TextureView>,
|
||||
view_count: usize,
|
||||
samplers: Vec<Sampler>,
|
||||
null_view: TextureView,
|
||||
no_views: Vec<TextureView>,
|
||||
}
|
||||
|
||||
impl GpuTextures {
|
||||
pub fn update(&mut self, textures: &mut Textures) -> bool {
|
||||
let mut changed = false;
|
||||
for update in textures.updates() {
|
||||
changed = true;
|
||||
match update {
|
||||
TextureUpdate::Push(image) => self.push(image),
|
||||
TextureUpdate::Set(i, image) => self.set(i, image),
|
||||
TextureUpdate::SetFree => self.view_count += 1,
|
||||
TextureUpdate::Free(i) => self.free(i),
|
||||
TextureUpdate::PushFree => self.push_free(),
|
||||
}
|
||||
}
|
||||
changed
|
||||
}
|
||||
fn set(&mut self, i: u32, image: &DynamicImage) {
|
||||
self.view_count += 1;
|
||||
let view = self.create_view(image);
|
||||
self.views[i as usize] = view;
|
||||
}
|
||||
fn free(&mut self, i: u32) {
|
||||
self.view_count -= 1;
|
||||
self.views[i as usize] = self.null_view.clone();
|
||||
}
|
||||
fn push(&mut self, image: &DynamicImage) {
|
||||
self.view_count += 1;
|
||||
let view = self.create_view(image);
|
||||
self.views.push(view);
|
||||
}
|
||||
fn push_free(&mut self) {
|
||||
self.view_count += 1;
|
||||
self.views.push(self.null_view.clone());
|
||||
}
|
||||
|
||||
fn create_view(&self, image: &DynamicImage) -> TextureView {
|
||||
let image = image.to_rgba8();
|
||||
let (width, height) = image.dimensions();
|
||||
let texture = self.device.create_texture_with_data(
|
||||
&self.queue,
|
||||
&TextureDescriptor {
|
||||
label: None,
|
||||
size: Extent3d {
|
||||
width,
|
||||
height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Rgba8Unorm,
|
||||
usage: TextureUsages::TEXTURE_BINDING,
|
||||
view_formats: &[],
|
||||
},
|
||||
wgt::TextureDataOrder::MipMajor,
|
||||
image.as_bytes(),
|
||||
);
|
||||
texture.create_view(&TextureViewDescriptor::default())
|
||||
}
|
||||
|
||||
pub fn new(device: &Device, queue: &Queue) -> Self {
|
||||
let null_view = null_texture_view(device);
|
||||
Self {
|
||||
device: device.clone(),
|
||||
queue: queue.clone(),
|
||||
views: Vec::new(),
|
||||
samplers: vec![default_sampler(device)],
|
||||
no_views: vec![null_view.clone()],
|
||||
null_view,
|
||||
view_count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn views(&self) -> Vec<&TextureView> {
|
||||
if self.views.is_empty() {
|
||||
&self.no_views
|
||||
} else {
|
||||
&self.views
|
||||
}
|
||||
.iter()
|
||||
.by_ref()
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn samplers(&self) -> Vec<&Sampler> {
|
||||
self.samplers.iter().by_ref().collect()
|
||||
}
|
||||
|
||||
pub fn view_count(&self) -> usize {
|
||||
self.view_count
|
||||
}
|
||||
}
|
||||
|
||||
pub fn null_texture_view(device: &Device) -> TextureView {
|
||||
device
|
||||
.create_texture(&TextureDescriptor {
|
||||
label: Some("null"),
|
||||
size: Extent3d {
|
||||
width: 1,
|
||||
height: 1,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Rgba8Unorm,
|
||||
usage: TextureUsages::TEXTURE_BINDING,
|
||||
view_formats: &[],
|
||||
})
|
||||
.create_view(&TextureViewDescriptor::default())
|
||||
}
|
||||
|
||||
pub fn default_sampler(device: &Device) -> Sampler {
|
||||
device.create_sampler(&SamplerDescriptor::default())
|
||||
}
|
||||
Reference in New Issue
Block a user