#![deny(unsafe_op_in_unsafe_fn)]
use concinnity_core::bake;
use concinnity_core::render::error::{RenderError, RenderResult};
use crate::metal::context::MtlContext;
use crate::metal::texture::{upload_texture, upload_texture_image};
impl MtlContext {
pub(crate) fn update_texture_slot(
&mut self,
slot: usize,
image: &concinnity_core::bake::texture::TextureImage,
) -> RenderResult<()> {
texture_slot_in_range("update_texture_slot", slot, self.scene.textures.len())?;
self.scene.textures[slot] = upload_texture_image(&self.hw.allocator, image)?;
self.arg_buffers.texture_epoch += 1;
Ok(())
}
pub(crate) fn evict_texture_slot(&mut self, slot: usize) -> RenderResult<()> {
texture_slot_in_range("evict_texture_slot", slot, self.scene.textures.len())?;
self.scene.textures[slot] =
upload_texture(&self.hw.allocator, 1, 1, &[128, 128, 128, 255])?;
self.arg_buffers.texture_epoch += 1;
Ok(())
}
pub(crate) fn update_color_lut(&mut self, size: u32, data: &[u8]) -> RenderResult<()> {
let tex = crate::metal::texture::upload_color_lut(&self.hw.allocator, size, data)?;
self.scene.color_lut = tex;
Ok(())
}
pub(crate) fn update_environment_map(&mut self, payload: &[u8]) -> RenderResult<()> {
let view = bake::environment_map::deserialize(payload)
.map_err(|e| RenderError::Other(format!("envmap hot-reload payload malformed: {e}")))?;
let new_env = crate::metal::texture::upload_environment_map(
&self.hw.allocator,
view.irradiance_face,
view.irradiance_bytes,
view.prefilter_face,
&view.prefilter_mip_bytes,
)?;
self.scene.env_map = new_env;
self.arg_buffers.texture_epoch += 1;
Ok(())
}
}
fn texture_slot_in_range(op: &str, slot: usize, pool_size: usize) -> RenderResult<()> {
if slot < pool_size {
Ok(())
} else {
Err(RenderError::Other(format!(
"{op}: slot {slot} out of range (pool size {pool_size})"
)))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn slot_inside_the_pool_is_accepted() {
assert_eq!(texture_slot_in_range("op", 0, 1), Ok(()));
assert_eq!(texture_slot_in_range("op", 3, 4), Ok(()));
}
#[test]
fn slot_at_or_past_the_pool_size_is_other() {
assert_eq!(
texture_slot_in_range("evict_texture_slot", 4, 4),
Err(RenderError::Other(
"evict_texture_slot: slot 4 out of range (pool size 4)".to_string()
))
);
assert!(texture_slot_in_range("op", 0, 0).is_err());
}
}