aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/draw/texture/chunk.rs
diff options
context:
space:
mode:
Diffstat (limited to 'stockton-render/src/draw/texture/chunk.rs')
-rw-r--r--stockton-render/src/draw/texture/chunk.rs152
1 files changed, 152 insertions, 0 deletions
diff --git a/stockton-render/src/draw/texture/chunk.rs b/stockton-render/src/draw/texture/chunk.rs
new file mode 100644
index 0000000..9356274
--- /dev/null
+++ b/stockton-render/src/draw/texture/chunk.rs
@@ -0,0 +1,152 @@
+// Copyright (C) 2019 Oscar Shrimpton
+
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option)
+// any later version.
+
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+
+//! A chunk of textures is an array of textures, the size of which is known at compile time.
+//! This reduces the number of times we need to re-bind our descriptor sets
+
+use image::{Rgba, RgbaImage};
+use hal::prelude::*;
+
+use core::{
+ mem::{replace}
+};
+use std::ops::{Range, Deref};
+
+use crate::{
+ types::*,
+ error
+};
+
+use log::debug;
+use super::resolver::TextureResolver;
+use super::image::LoadedImage;
+use stockton_levels::prelude::*;
+
+/// The size of a chunk. Needs to match up with the fragment shader
+pub const CHUNK_SIZE: usize = 8;
+
+/// An array of textures
+pub struct TextureChunk {
+ pub(crate) descriptor_set: DescriptorSet,
+ loaded_images: Vec<LoadedImage>,
+}
+
+impl TextureChunk {
+ pub fn new<T: HasTextures, R: TextureResolver>(device: &mut Device,
+ adapter: &mut Adapter,
+ command_queue: &mut CommandQueue,
+ command_pool: &mut CommandPool,
+ pool: &mut DescriptorPool,
+ layout: &DescriptorSetLayout,
+ file: &T, range: Range<u32>,
+ resolver: &mut R) -> Result<TextureChunk, error::CreationError> {
+
+ let descriptor_set = unsafe {
+ pool.allocate_set(&layout).map_err(|e| {
+ println!("{:?}", e);
+ error::CreationError::OutOfMemoryError
+ })?
+ };
+
+ let mut store = TextureChunk {
+ descriptor_set: descriptor_set,
+ loaded_images: Vec::with_capacity(CHUNK_SIZE),
+ };
+
+ let mut local_idx = 0;
+
+ debug!("Created descriptor set");
+ for tex_idx in range {
+ debug!("Loading tex {}", local_idx + 1);
+ let tex = file.get_texture(tex_idx);
+ let img = resolver.resolve(tex);
+ store.put_texture(img, local_idx,
+ device, adapter,
+ command_queue, command_pool).unwrap();
+
+ local_idx += 1;
+ }
+
+ // Pad out the end if needed
+ while local_idx < CHUNK_SIZE {
+ debug!("Putting a placeholder in slot {}", local_idx);
+ store.put_texture(RgbaImage::from_pixel(1, 1, Rgba ([0, 0, 0, 1])), local_idx,
+ device, adapter,
+ command_queue, command_pool).unwrap();
+
+ local_idx += 1;
+ }
+
+ Ok(store)
+ }
+
+
+ pub fn put_texture(&mut self, image: RgbaImage,
+ idx: usize,
+ device: &mut Device,
+ adapter: &mut Adapter,
+ command_queue: &mut CommandQueue,
+ command_pool: &mut CommandPool) -> Result<(), &'static str>{
+
+ // Load the image
+ let texture = LoadedImage::load(
+ image,
+ device,
+ adapter,
+ command_queue,
+ command_pool,
+ )?;
+
+ // Write it to the descriptor set
+ unsafe {
+ use hal::pso::{DescriptorSetWrite, Descriptor};
+ use hal::image::Layout;
+
+ device.write_descriptor_sets(vec![
+ DescriptorSetWrite {
+ set: &self.descriptor_set,
+ binding: 0,
+ array_offset: idx,
+ descriptors: Some(Descriptor::Image(
+ texture.image_view.deref(),
+ Layout::ShaderReadOnlyOptimal
+ )),
+ },
+ DescriptorSetWrite {
+ set: &self.descriptor_set,
+ binding: 1,
+ array_offset: idx,
+ descriptors: Some(Descriptor::Sampler(texture.sampler.deref())),
+ },
+ ]);
+ };
+
+ // Store it so we can safely deactivate it when we need to
+ // Deactivate the old image if we need to
+ if idx < self.loaded_images.len() {
+ replace(&mut self.loaded_images[idx], texture).deactivate(device);
+ } else {
+ self.loaded_images.push(texture);
+ }
+
+ Ok(())
+ }
+
+ pub fn deactivate(mut self, device: &mut Device) -> () {
+ for img in self.loaded_images.drain(..) {
+ img.deactivate(device);
+ }
+ }
+} \ No newline at end of file