<commit_before>use classfile_parser::method_info::{PUBLIC, STATIC, NATIVE};
use class_loader::ClassLoader;
use instruction::{Instruction, LocalVarRef};
use instruction::Instruction::*;
use instruction::Type::*;
use parsed_class::MethodRef;
use std::mem;
use std::cmp::max;
use std::ops::Mul;

// USE WITH CARE
macro_rules! conv { ($val: expr) => {{unsafe {mem::transmute($val)}}} }

pub struct VM {
    classloader: ClassLoader,
    frames: Vec<Frame>,
    // TODO #[cfg(debug)]
    native_calls: Vec<(String, String, Vec<i32>)>,
}

pub struct Frame {
    // arrays are to big to create them on the stack
    // TODO think about using maybe Box<Frame> with arrays
    //  => benchmark
    code: Vec<Instruction>,
    ip: usize,
    sp: usize,
    local_vars: Vec<i32>,
    stack: Vec<i32>,
}

impl VM {
    pub fn new(loader: ClassLoader) -> VM {
        VM {
            native_calls: Vec::new(),
            classloader: loader,
            frames: Vec::new(),
        }
    }

    // TODO think about using a real error type here
    pub fn start(&mut self, class: &str, _args: &[&str]) -> Result<(), String> {
        let class_name;
        {
            let start_class = self.classloader.load_class(class).map_err(|err| format!("ClassLoadingError: {}", err))?;

            let main = match start_class.method_by_signature("main", "([Ljava/lang/String;)V") {
                Some(m) => m,
                None => return Err("No main method found!".to_owned()),
            };

            if main.access_flags() != PUBLIC | STATIC {
                return Err(format!("invalid access flags for main: {:?}", main.access_flags()));
            }

            class_name = start_class.name().to_owned();
        }
        let mut start_frame = Frame::dummy_frame(0);
        // TODO push args on the stack
        self.invoke_method(&class_name,
                           "main",
                           "([Ljava/lang/String;)V",
                           &mut start_frame);

        self.run(start_frame);
        Ok(())
    }

    pub fn invoke_method(&mut self, class_name: &str, method: &str, descriptor: &str, calling_frame: &mut Frame) {
        // these unwraps should be checked in the linking stage
        let method = self.classloader.load_class(class_name).unwrap().method_by_signature(method, descriptor).unwrap();

        let mut local_vars;
        let code;
        {
            let args = &calling_frame.stack[calling_frame.sp - method.words_for_params()..calling_frame.sp];
            calling_frame.sp -= method.words_for_params();

            if method.access_flags().contains(NATIVE) {
                self.native_calls.push((method.name().to_owned(), method.descriptor().to_owned(), args.to_vec()));
                // TODO real handling of call
                return;
            }

            code = method.code().expect("Method must have code");
            // println!("Code: {:?}", code);

            local_vars = Vec::with_capacity(code.max_locals());
            local_vars.resize(code.max_locals(), 0);
            local_vars[..args.len()].copy_from_slice(args);
        }
        let mut stack = Vec::with_capacity(code.max_stack());
        stack.resize(code.max_stack(), 0);

        let mut new_frame = Frame {
            ip: 0,
            sp: 0,
            local_vars: local_vars,
            stack: stack,
            code: code.code().clone(),
        };
        mem::swap(&mut new_frame, calling_frame);
        self.frames.push(new_frame);
    }

    pub fn invoke_method_ref(&mut self, method: &MethodRef, calling_frame: &mut Frame) {
        self.invoke_method(method.class(),
                           method.name(),
                           method.descriptor(),
                           calling_frame)
    }

    fn run(&mut self, start_frame: Frame) {
        self.frames.pop().expect("Expected dummy frame on frame stack");
        assert_eq!(self.frames.len(), 0);
        let mut frame = start_frame;

        macro_rules! arith_int(($typ: ident, $op:ident) => {{
            match $typ {
                Int => {
                    let b: i32 = conv!(frame.pop());
                    let a: i32 = conv!(frame.pop());
                    frame.push(conv!(a.$op(b)));
                }
                Long => {
                    let b: i64 = conv!(frame.pop2());
                    let a: i64 = conv!(frame.pop2());
                    frame.push2(conv!(a.$op(b)));
                }
                t@_ => panic!("Operation {} is not implemented for typ {:?}", stringify!($op), t),
            }
        }});

        macro_rules! arith_float(($typ: ident, $op:ident) => {{
            match $typ {
                Float => {
                    let b: f32 = conv!(frame.pop());
                    let a: f32 = conv!(frame.pop());
                    frame.push(conv!(a.$op(b)));
                }
                Double => {
                    let b: f64 = conv!(frame.pop2());
                    let a: f64 = conv!(frame.pop2());
                    frame.push2(conv!(a.$op(b)));
                }
                t@_ => panic!("Operation {} is not implemented for typ {:?}", stringify!($op), t),
            }
        }});

        loop {
            match frame.next() {
                STORE(typ, idx) => {
                    if typ.is_double_sized() {
                        // TODO test
                        let v = frame.pop2();
                        frame.store2(idx, v);
                    } else {
                        let v = frame.pop();
                        frame.store(idx, v);
                    }
                }
                LOAD(typ, idx) => {
                    if typ.is_double_sized() {
                        let v = frame.load2(idx);
                        frame.push2(v);
                    } else {
                        let v = frame.load(idx);
                        frame.push(v);
                    }
                }
                MUL(t @ Int) | MUL(t @ Long) => arith_int!(t, wrapping_mul),
                MUL(t) => arith_float!(t, mul),
                // MUL(Int) => {
                // let a: i32 = conv!(frame.pop());
                // let b: i32 = conv!(frame.pop());
                // frame.push(a.wrapping_mul(b));
                // }
                RETURN(o) => {
                    if self.frames.is_empty() {
                        return;
                    }
                    let mut old_frame = frame;
                    frame = self.frames.pop().unwrap();

                    if let Some(typ) = o {
                        if typ.is_double_sized() {
                            // TODO test
                            let v2 = old_frame.pop2();
                            frame.push2(v2);
                        } else {
                            let v = old_frame.pop();
                            frame.push(v);
                        }
                    }
                }
                ACONST_NULL => frame.push(0),
                DCONST_0 => frame.push2(conv!(0f64)),
                DCONST_1 => frame.push2(conv!(1f64)),
                FCONST_0 => frame.push(conv!(0f32)),
                FCONST_1 => frame.push(conv!(1f32)),
                FCONST_2 => frame.push(conv!(2f32)),
                LCONST_0 => frame.push2(conv!(0i64)),
                LCONST_1 => frame.push2(conv!(1i64)),
                BIPUSH(i) => frame.push(i as i32),
                SIPUSH(i) => frame.push(i as i32),
                LDC_INT(i) => frame.push(i),
                LDC_FLOAT(f) => frame.push(conv!(f)),
                // TODO LDC_STRING(String) => frame.push(),
                LDC_DOUBLE(f) => frame.push2(conv!(f)),
                LDC_LONG(i) => frame.push2(conv!(i)),
                INVOKESTATIC(method) => {
                    self.invoke_method_ref(&method, &mut frame);
                }
                c @ _ => panic!("Not implemented Instruction {:?}", c),
            }
        }
    }
}

impl Frame {
    fn dummy_frame(stack_size: usize) -> Frame {
        let mut stack = Vec::with_capacity(stack_size);
        stack.resize(stack_size, 0);
        Frame {
            ip: 0,
            sp: 0,
            stack: stack,
            local_vars: Vec::new(),
            code: Vec::new(),
        }
    }

    #[inline(always)]
    fn next(&mut self) -> Instruction {
        let instruction = self.code[self.ip].clone();
        self.ip += 1;
        instruction
    }

    #[inline(always)]
    fn push(&mut self, val: i32) {
        self.stack[self.sp] = val;
        self.sp += 1;
    }

    #[inline(always)]
    fn push2(&mut self, val: [i32; 2]) {
        self.push(val[0]);
        self.push(val[1]);
    }

    #[inline(always)]
    fn pop(&mut self) -> i32 {
        self.sp -= 1;
        self.stack[self.sp]
    }

    #[inline(always)]
    fn pop2(&mut self) -> [i32; 2] {
        let b = self.pop();
        let a = self.pop();
        [a, b]
    }

    #[inline(always)]
    fn store(&mut self, index: LocalVarRef, val: i32) { self.local_vars[index as usize] = val; }

    #[inline(always)]
    fn store2(&mut self, index: LocalVarRef, val: [i32; 2]) {
        self.store(index, val[0]);
        self.store(index + 1, val[1]);
    }

    #[inline(always)]
    fn load(&self, index: LocalVarRef) -> i32 { self.local_vars[index as usize] }

    #[inline(always)]
    fn load2(&mut self, index: LocalVarRef) -> [i32; 2] { [self.load(index), self.load(index + 1)] }
}

#[cfg(test)]
mod tests {
    macro_rules! arg1 { ($val: expr) => {{vec![unsafe {mem::transmute::<_, i32>($val)}]}} }
    macro_rules! arg2 { ($val: expr) => {{unsafe {mem::transmute::<_, [i32; 2]>($val)}.to_vec()}} }
    use super::*;

    fn run(class: &str, method: &str, native_calls: Vec<(&str, Vec<i32>)>) {
        let classloader = ClassLoader::new("./assets");
        let mut vm = VM::new(classloader);
        let mut start_frame = Frame::dummy_frame(0);
        vm.invoke_method(class, method, "()V", &mut start_frame);
        vm.run(start_frame);

        for index in 0..max(native_calls.len(), vm.native_calls.len()) {
            if index >= native_calls.len() {
                println!("[{}] Additional Calls: {:?}",
                         method,
                         &vm.native_calls[index..]);
                panic!("FAIL");
            }
            if index >= vm.native_calls.len() {
                println!("[{}] Missing Calls: {:?}", method, &native_calls[index..]);
                panic!("FAIL");
            }
            assert_eq!((native_calls[index].0, &native_calls[index].1),
                       (vm.native_calls[index].0.as_str(), &vm.native_calls[index].2));
        }
    }

    #[test]
    fn print_class() {
        let mut classloader = ClassLoader::new("./assets");
        let class = classloader.load_class("TestVM").unwrap();
        for method in class.methods() {
            println!("Method {} {}:", method.descriptor(), method.name());
            match method.code() {
                Some(c) => {
                    for instr in c.code() {
                        println!("  {:?}", instr);
                    }
                }
                None => println!("  No code!"),
            }
            println!();
        }
    }

    #[test]
    fn simple() { run("TestVM", "simple", vec![("nativeInt", vec![1])]); }

    #[test]
    fn staticcall() {
        run("TestVM",
            "staticcall",
            vec![("nativeLong", arg2!(1i64)),
                 ("nativeLong", arg2!(2i64)),
                 ("nativeLong", arg2!(2i64))]);
    }

    #[test]
    fn mul() {
        run("TestVM",
            "mul",
            vec![("nativeInt", arg1!(8)),
                 ("nativeInt", arg1!(4)),
                 ("nativeLong", arg2!(8i64)),
                 ("nativeLong", arg2!(0x400000010i64)),
                 ("nativeLong", arg2!(4i64)),
                 ("nativeFloat", arg1!(0.2f32)),
                 ("nativeDouble", arg2!(0.2f64)),
            ]);
    }

    #[test]
    fn constants() {
        run("TestVM",
            "constants",
            vec![("nativeInt", arg1!(0)),
                 ("nativeInt", arg1!(1337)),
                 ("nativeInt", arg1!(0x4000000)),
                 ("nativeFloat", arg1!(0f32)),
                 ("nativeFloat", arg1!(1f32)),
                 ("nativeFloat", arg1!(2f32)),
                 ("nativeFloat", arg1!(1.337f32)),
                 ("nativeDouble", arg2!(0f64)),
                 ("nativeDouble", arg2!(1f64)),
                 ("nativeDouble", arg2!(1.337f64)),
                 ("nativeLong", arg2!(0i64)),
                 ("nativeLong", arg2!(1i64)),
                 ("nativeLong", arg2!(1337i64)),
                 ("nativeString", arg1!(0))]);
    }
}
<commit_msg>formatted vm<commit_after>use classfile_parser::method_info::{PUBLIC, STATIC, NATIVE};
use class_loader::ClassLoader;
use instruction::{Instruction, LocalVarRef};
use instruction::Instruction::*;
use instruction::Type::*;
use parsed_class::MethodRef;
use std::mem;
use std::cmp::max;
use std::ops::Mul;

// USE WITH CARE
macro_rules! conv { ($val: expr) => {{unsafe {mem::transmute($val)}}} }

pub struct VM {
    classloader: ClassLoader,
    frames: Vec<Frame>,
    // TODO #[cfg(debug)]
    native_calls: Vec<(String, String, Vec<i32>)>,
}

pub struct Frame {
    // arrays are to big to create them on the stack
    // TODO think about using maybe Box<Frame> with arrays
    //  => benchmark
    code: Vec<Instruction>,
    ip: usize,
    sp: usize,
    local_vars: Vec<i32>,
    stack: Vec<i32>,
}

impl VM {
    pub fn new(loader: ClassLoader) -> VM {
        VM {
            native_calls: Vec::new(),
            classloader: loader,
            frames: Vec::new(),
        }
    }

    // TODO think about using a real error type here
    pub fn start(&mut self, class: &str, _args: &[&str]) -> Result<(), String> {
        let class_name;
        {
            let start_class = self.classloader.load_class(class).map_err(|err| format!("ClassLoadingError: {}", err))?;

            let main = match start_class.method_by_signature("main", "([Ljava/lang/String;)V") {
                Some(m) => m,
                None => return Err("No main method found!".to_owned()),
            };

            if main.access_flags() != PUBLIC | STATIC {
                return Err(format!("invalid access flags for main: {:?}", main.access_flags()));
            }

            class_name = start_class.name().to_owned();
        }
        let mut start_frame = Frame::dummy_frame(0);
        // TODO push args on the stack
        self.invoke_method(&class_name,
                           "main",
                           "([Ljava/lang/String;)V",
                           &mut start_frame);

        self.run(start_frame);
        Ok(())
    }

    pub fn invoke_method(&mut self, class_name: &str, method: &str, descriptor: &str, calling_frame: &mut Frame) {
        // these unwraps should be checked in the linking stage
        let method = self.classloader.load_class(class_name).unwrap().method_by_signature(method, descriptor).unwrap();

        let mut local_vars;
        let code;
        {
            let args = &calling_frame.stack[calling_frame.sp - method.words_for_params()..calling_frame.sp];
            calling_frame.sp -= method.words_for_params();

            if method.access_flags().contains(NATIVE) {
                self.native_calls.push((method.name().to_owned(), method.descriptor().to_owned(), args.to_vec()));
                // TODO real handling of call
                return;
            }

            code = method.code().expect("Method must have code");
            // println!("Code: {:?}", code);

            local_vars = Vec::with_capacity(code.max_locals());
            local_vars.resize(code.max_locals(), 0);
            local_vars[..args.len()].copy_from_slice(args);
        }
        let mut stack = Vec::with_capacity(code.max_stack());
        stack.resize(code.max_stack(), 0);

        let mut new_frame = Frame {
            ip: 0,
            sp: 0,
            local_vars: local_vars,
            stack: stack,
            code: code.code().clone(),
        };
        mem::swap(&mut new_frame, calling_frame);
        self.frames.push(new_frame);
    }

    pub fn invoke_method_ref(&mut self, method: &MethodRef, calling_frame: &mut Frame) {
        self.invoke_method(method.class(),
                           method.name(),
                           method.descriptor(),
                           calling_frame)
    }

    fn run(&mut self, start_frame: Frame) {
        self.frames.pop().expect("Expected dummy frame on frame stack");
        assert_eq!(self.frames.len(), 0);
        let mut frame = start_frame;

        macro_rules! arith_int(($typ: ident, $op:ident) => {{
            match $typ {
                Int => {
                    let b: i32 = conv!(frame.pop());
                    let a: i32 = conv!(frame.pop());
                    frame.push(conv!(a.$op(b)));
                }
                Long => {
                    let b: i64 = conv!(frame.pop2());
                    let a: i64 = conv!(frame.pop2());
                    frame.push2(conv!(a.$op(b)));
                }
                t@_ => panic!("Operation {} is not implemented for typ {:?}", stringify!($op), t),
            }
        }});

        macro_rules! arith_float(($typ: ident, $op:ident) => {{
            match $typ {
                Float => {
                    let b: f32 = conv!(frame.pop());
                    let a: f32 = conv!(frame.pop());
                    frame.push(conv!(a.$op(b)));
                }
                Double => {
                    let b: f64 = conv!(frame.pop2());
                    let a: f64 = conv!(frame.pop2());
                    frame.push2(conv!(a.$op(b)));
                }
                t@_ => panic!("Operation {} is not implemented for typ {:?}", stringify!($op), t),
            }
        }});

        loop {
            match frame.next() {
                STORE(typ, idx) => {
                    if typ.is_double_sized() {
                        // TODO test
                        let v = frame.pop2();
                        frame.store2(idx, v);
                    } else {
                        let v = frame.pop();
                        frame.store(idx, v);
                    }
                }
                LOAD(typ, idx) => {
                    if typ.is_double_sized() {
                        let v = frame.load2(idx);
                        frame.push2(v);
                    } else {
                        let v = frame.load(idx);
                        frame.push(v);
                    }
                }
                MUL(t @ Int) | MUL(t @ Long) => arith_int!(t, wrapping_mul),
                MUL(t) => arith_float!(t, mul),
                // MUL(Int) => {
                // let a: i32 = conv!(frame.pop());
                // let b: i32 = conv!(frame.pop());
                // frame.push(a.wrapping_mul(b));
                // }
                RETURN(o) => {
                    if self.frames.is_empty() {
                        return;
                    }
                    let mut old_frame = frame;
                    frame = self.frames.pop().unwrap();

                    if let Some(typ) = o {
                        if typ.is_double_sized() {
                            // TODO test
                            let v2 = old_frame.pop2();
                            frame.push2(v2);
                        } else {
                            let v = old_frame.pop();
                            frame.push(v);
                        }
                    }
                }
                ACONST_NULL => frame.push(0),
                DCONST_0 => frame.push2(conv!(0f64)),
                DCONST_1 => frame.push2(conv!(1f64)),
                FCONST_0 => frame.push(conv!(0f32)),
                FCONST_1 => frame.push(conv!(1f32)),
                FCONST_2 => frame.push(conv!(2f32)),
                LCONST_0 => frame.push2(conv!(0i64)),
                LCONST_1 => frame.push2(conv!(1i64)),
                BIPUSH(i) => frame.push(i as i32),
                SIPUSH(i) => frame.push(i as i32),
                LDC_INT(i) => frame.push(i),
                LDC_FLOAT(f) => frame.push(conv!(f)),
                // TODO LDC_STRING(String) => frame.push(),
                LDC_DOUBLE(f) => frame.push2(conv!(f)),
                LDC_LONG(i) => frame.push2(conv!(i)),
                INVOKESTATIC(method) => {
                    self.invoke_method_ref(&method, &mut frame);
                }
                c @ _ => panic!("Not implemented Instruction {:?}", c),
            }
        }
    }
}

impl Frame {
    fn dummy_frame(stack_size: usize) -> Frame {
        let mut stack = Vec::with_capacity(stack_size);
        stack.resize(stack_size, 0);
        Frame {
            ip: 0,
            sp: 0,
            stack: stack,
            local_vars: Vec::new(),
            code: Vec::new(),
        }
    }

    #[inline(always)]
    fn next(&mut self) -> Instruction {
        let instruction = self.code[self.ip].clone();
        self.ip += 1;
        instruction
    }

    #[inline(always)]
    fn push(&mut self, val: i32) {
        self.stack[self.sp] = val;
        self.sp += 1;
    }

    #[inline(always)]
    fn push2(&mut self, val: [i32; 2]) {
        self.push(val[0]);
        self.push(val[1]);
    }

    #[inline(always)]
    fn pop(&mut self) -> i32 {
        self.sp -= 1;
        self.stack[self.sp]
    }

    #[inline(always)]
    fn pop2(&mut self) -> [i32; 2] {
        let b = self.pop();
        let a = self.pop();
        [a, b]
    }

    #[inline(always)]
    fn store(&mut self, index: LocalVarRef, val: i32) { self.local_vars[index as usize] = val; }

    #[inline(always)]
    fn store2(&mut self, index: LocalVarRef, val: [i32; 2]) {
        self.store(index, val[0]);
        self.store(index + 1, val[1]);
    }

    #[inline(always)]
    fn load(&self, index: LocalVarRef) -> i32 { self.local_vars[index as usize] }

    #[inline(always)]
    fn load2(&mut self, index: LocalVarRef) -> [i32; 2] { [self.load(index), self.load(index + 1)] }
}

#[cfg(test)]
mod tests {
    macro_rules! arg1 { ($val: expr) => {{vec![unsafe {mem::transmute::<_, i32>($val)}]}} }
    macro_rules! arg2 { ($val: expr) => {{unsafe {mem::transmute::<_, [i32; 2]>($val)}.to_vec()}} }
    use super::*;

    fn run(class: &str, method: &str, native_calls: Vec<(&str, Vec<i32>)>) {
        let classloader = ClassLoader::new("./assets");
        let mut vm = VM::new(classloader);
        let mut start_frame = Frame::dummy_frame(0);
        vm.invoke_method(class, method, "()V", &mut start_frame);
        vm.run(start_frame);

        for index in 0..max(native_calls.len(), vm.native_calls.len()) {
            if index >= native_calls.len() {
                println!("[{}] Additional Calls: {:?}",
                         method,
                         &vm.native_calls[index..]);
                panic!("FAIL");
            }
            if index >= vm.native_calls.len() {
                println!("[{}] Missing Calls: {:?}", method, &native_calls[index..]);
                panic!("FAIL");
            }
            assert_eq!((native_calls[index].0, &native_calls[index].1),
                       (vm.native_calls[index].0.as_str(), &vm.native_calls[index].2));
        }
    }

    #[test]
    fn print_class() {
        let mut classloader = ClassLoader::new("./assets");
        let class = classloader.load_class("TestVM").unwrap();
        for method in class.methods() {
            println!("Method {} {}:", method.descriptor(), method.name());
            match method.code() {
                Some(c) => {
                    for instr in c.code() {
                        println!("  {:?}", instr);
                    }
                }
                None => println!("  No code!"),
            }
            println!();
        }
    }

    #[test]
    fn simple() { run("TestVM", "simple", vec![("nativeInt", vec![1])]); }

    #[test]
    fn staticcall() {
        run("TestVM",
            "staticcall",
            vec![("nativeLong", arg2!(1i64)), ("nativeLong", arg2!(2i64)), ("nativeLong", arg2!(2i64))]);
    }

    #[test]
    fn mul() {
        run("TestVM",
            "mul",
            vec![("nativeInt", arg1!(8)),
                 ("nativeInt", arg1!(4)),
                 ("nativeLong", arg2!(8i64)),
                 ("nativeLong", arg2!(0x400000010i64)),
                 ("nativeLong", arg2!(4i64)),
                 ("nativeFloat", arg1!(0.2f32)),
                 ("nativeDouble", arg2!(0.2f64))]);
    }

    #[test]
    fn constants() {
        run("TestVM",
            "constants",
            vec![("nativeInt", arg1!(0)),
                 ("nativeInt", arg1!(1337)),
                 ("nativeInt", arg1!(0x4000000)),
                 ("nativeFloat", arg1!(0f32)),
                 ("nativeFloat", arg1!(1f32)),
                 ("nativeFloat", arg1!(2f32)),
                 ("nativeFloat", arg1!(1.337f32)),
                 ("nativeDouble", arg2!(0f64)),
                 ("nativeDouble", arg2!(1f64)),
                 ("nativeDouble", arg2!(1.337f64)),
                 ("nativeLong", arg2!(0i64)),
                 ("nativeLong", arg2!(1i64)),
                 ("nativeLong", arg2!(1337i64)),
                 ("nativeString", arg1!(0))]);
    }
}
<|endoftext|>


<commit_before>use crate::{math::interpolate, noise_fns::NoiseFn, permutationtable::NoiseHasher, utils::noise_map::NoiseMap};

pub struct NoiseFnWrapper<NH, F, const DIM: usize>
where
    NH: NoiseHasher,
    F: Fn([f64; DIM], &NH) -> f64,
{
    hasher: NH,
    func: F,
}

impl<NH, F, const DIM: usize> NoiseFn<f64, DIM> for NoiseFnWrapper<NH, F, DIM>
where
    NH: NoiseHasher,
    F: Fn([f64; DIM], &NH) -> f64,
{
    fn get(&self, point: [f64; DIM]) -> f64 {
        (self.func)(point, &self.hasher)
    }
}

fn pad_array<const SIZE: usize>(values: &[f64]) -> [f64; SIZE] {
    let mut result = [0.0; SIZE];

    result[..values.len().min(SIZE)].clone_from_slice(&values[..values.len().min(SIZE)]);

    result
}

pub trait NoiseMapBuilder<SourceModule> {
    fn set_size(self, width: usize, height: usize) -> Self;

    fn set_source_module(self, source_module: SourceModule) -> Self;

    fn size(&self) -> (usize, usize);

    fn build(&self) -> NoiseMap;
}

pub struct CylinderMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    angle_bounds: (f64, f64),
    height_bounds: (f64, f64),
    size: (usize, usize),
    source_module: SourceModule,
}

impl<SourceModule> CylinderMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    pub fn new(source_module: SourceModule) -> Self {
        CylinderMapBuilder {
            angle_bounds: (-90.0, 90.0),
            height_bounds: (-1.0, 1.0),
            size: (100, 100),
            source_module,
        }
    }

    pub fn set_angle_bounds(self, lower_bound: f64, upper_bound: f64) -> Self {
        let angle_bounds = if lower_bound >= upper_bound {
            // eprintln!(
            //     "lower bound {:?} is larger than upper bound {:?}, switching order",
            //     lower_bound, upper_bound
            // );
            (upper_bound, lower_bound)
        } else {
            (lower_bound, upper_bound)
        };

        CylinderMapBuilder {
            angle_bounds,
            ..self
        }
    }

    pub fn set_height_bounds(self, lower_bound: f64, upper_bound: f64) -> Self {
        let height_bounds = if lower_bound >= upper_bound {
            // eprintln!(
            //     "lower bound {:?} is larger than upper bound {:?}, switching order",
            //     lower_bound, upper_bound
            // );
            (upper_bound, lower_bound)
        } else {
            (lower_bound, upper_bound)
        };

        CylinderMapBuilder {
            height_bounds,
            ..self
        }
    }

    pub fn angle_bounds(&self) -> (f64, f64) {
        self.angle_bounds
    }

    pub fn height_bounds(&self) -> (f64, f64) {
        self.height_bounds
    }
}

impl<SourceModule> NoiseMapBuilder<SourceModule> for CylinderMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    fn set_size(self, width: usize, height: usize) -> Self {
        CylinderMapBuilder {
            size: (width, height),
            ..self
        }
    }

    fn set_source_module(self, source_module: SourceModule) -> Self {
        CylinderMapBuilder {
            source_module,
            ..self
        }
    }

    fn size(&self) -> (usize, usize) {
        self.size
    }

    fn build(&self) -> NoiseMap {
        let mut result_map = NoiseMap::new(self.size.0, self.size.1);

        let (width, height) = self.size;

        let angle_extent = self.angle_bounds.1 - self.angle_bounds.0;
        let height_extent = self.height_bounds.1 - self.height_bounds.0;

        let x_step = angle_extent / width as f64;
        let y_step = height_extent / height as f64;

        for y in 0..height {
            let current_height = self.height_bounds.0 + y_step * y as f64;

            for x in 0..width {
                let current_angle = self.angle_bounds.0 + x_step * x as f64;

                let point_x = current_angle.to_radians().cos();
                let point_z = current_angle.to_radians().sin();

                let value = self.source_module.get([point_x, current_height, point_z]);

                // println!(
                //     "calculated value {} at {}, {}, {}",
                //     value, point_x, current_height, point_z
                // );

                result_map[(x, y)] = value;
            }
        }

        result_map
    }
}

pub struct PlaneMapBuilder<SourceModule, const DIM: usize>
where
    SourceModule: NoiseFn<f64, DIM>,
{
    is_seamless: bool,
    x_bounds: (f64, f64),
    y_bounds: (f64, f64),
    size: (usize, usize),
    source_module: SourceModule,
}

impl<NH, F, const DIM: usize> PlaneMapBuilder<NoiseFnWrapper<NH, F, DIM>, DIM>
where
    NH: NoiseHasher + Clone,
    F: Fn([f64; DIM], &NH) -> f64,
{
    pub fn new_fn(func: F, hasher: &NH) -> Self {
        PlaneMapBuilder {
            is_seamless: false,
            x_bounds: (-1.0, 1.0),
            y_bounds: (-1.0, 1.0),
            size: (100, 100),
            source_module: NoiseFnWrapper {
                hasher: hasher.clone(),
                func,
            },
        }
    }
}

impl<SourceModule, const DIM: usize> PlaneMapBuilder<SourceModule, DIM>
where
    SourceModule: NoiseFn<f64, DIM>,
{
    pub fn new(source_module: SourceModule) -> Self {
        PlaneMapBuilder {
            is_seamless: false,
            x_bounds: (-1.0, 1.0),
            y_bounds: (-1.0, 1.0),
            size: (100, 100),
            source_module,
        }
    }

    pub fn set_is_seamless(self, is_seamless: bool) -> Self {
        PlaneMapBuilder {
            is_seamless,
            ..self
        }
    }

    pub fn set_x_bounds(self, lower_x_bound: f64, upper_x_bound: f64) -> Self {
        PlaneMapBuilder {
            x_bounds: (lower_x_bound, upper_x_bound),
            ..self
        }
    }

    pub fn set_y_bounds(self, lower_y_bound: f64, upper_y_bound: f64) -> Self {
        PlaneMapBuilder {
            y_bounds: (lower_y_bound, upper_y_bound),
            ..self
        }
    }

    pub fn x_bounds(&self) -> (f64, f64) {
        self.x_bounds
    }

    pub fn y_bounds(&self) -> (f64, f64) {
        self.y_bounds
    }
}

impl<SourceModule, const DIM: usize> NoiseMapBuilder<SourceModule> for PlaneMapBuilder<SourceModule, DIM>
where
    SourceModule: NoiseFn<f64, DIM>,
{
    fn set_size(self, width: usize, height: usize) -> Self {
        PlaneMapBuilder {
            size: (width, height),
            ..self
        }
    }

    fn set_source_module(self, source_module: SourceModule) -> Self {
        PlaneMapBuilder {
            source_module,
            ..self
        }
    }

    fn size(&self) -> (usize, usize) {
        self.size
    }

    fn build(&self) -> NoiseMap {
        let (width, height) = self.size;

        let mut result_map = NoiseMap::new(width, height);

        let x_extent = self.x_bounds.1 - self.x_bounds.0;
        let y_extent = self.y_bounds.1 - self.y_bounds.0;

        let x_step = x_extent / width as f64;
        let y_step = y_extent / height as f64;

        for y in 0..height {
            let current_y = self.y_bounds.0 + y_step * y as f64;

            for x in 0..width {
                let current_x = self.x_bounds.0 + x_step * x as f64;

                let final_value = if self.is_seamless {
                    let sw_value = self.source_module.get(pad_array(&[current_x, current_y]));
                    let se_value = self
                        .source_module
                        .get(pad_array(&[current_x + x_extent, current_y]));
                    let nw_value = self
                        .source_module
                        .get(pad_array(&[current_x, current_y + y_extent]));
                    let ne_value =
                        self.source_module
                            .get(pad_array(&[current_x + x_extent, current_y + y_extent]));

                    let x_blend = 1.0 - ((current_x - self.x_bounds.0) / x_extent);
                    let y_blend = 1.0 - ((current_y - self.y_bounds.0) / y_extent);

                    let y0 = interpolate::linear(sw_value, se_value, x_blend);
                    let y1 = interpolate::linear(nw_value, ne_value, x_blend);

                    interpolate::linear(y0, y1, y_blend)
                } else {
                    self.source_module.get(pad_array(&[current_x, current_y]))
                };

                result_map[(x, y)] = final_value;
            }
        }

        result_map
    }
}

pub struct SphereMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    latitude_bounds: (f64, f64),
    longitude_bounds: (f64, f64),
    size: (usize, usize),
    source_module: SourceModule,
}

impl<SourceModule> SphereMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    pub fn new(source_module: SourceModule) -> Self {
        SphereMapBuilder {
            latitude_bounds: (-1.0, 1.0),
            longitude_bounds: (-1.0, 1.0),
            size: (100, 100),
            source_module,
        }
    }

    pub fn set_latitude_bounds(self, min_lat_bound: f64, max_lat_bound: f64) -> Self {
        SphereMapBuilder {
            latitude_bounds: (min_lat_bound, max_lat_bound),
            ..self
        }
    }

    pub fn set_longitude_bounds(self, min_lon_bound: f64, max_lon_bound: f64) -> Self {
        SphereMapBuilder {
            longitude_bounds: (min_lon_bound, max_lon_bound),
            ..self
        }
    }

    pub fn set_bounds(
        self,
        min_lat_bound: f64,
        max_lat_bound: f64,
        min_lon_bound: f64,
        max_lon_bound: f64,
    ) -> Self {
        SphereMapBuilder {
            latitude_bounds: (min_lat_bound, max_lat_bound),
            longitude_bounds: (min_lon_bound, max_lon_bound),
            ..self
        }
    }

    pub fn latitude_bounds(&self) -> (f64, f64) {
        self.latitude_bounds
    }

    pub fn longitude_bounds(&self) -> (f64, f64) {
        self.longitude_bounds
    }
}

impl<SourceModule> NoiseMapBuilder<SourceModule> for SphereMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    fn set_size(self, width: usize, height: usize) -> Self {
        SphereMapBuilder {
            size: (width, height),
            ..self
        }
    }

    fn set_source_module(self, source_module: SourceModule) -> Self {
        SphereMapBuilder {
            source_module,
            ..self
        }
    }

    fn size(&self) -> (usize, usize) {
        self.size
    }

    fn build(&self) -> NoiseMap {
        let (width, height) = self.size;

        let mut result_map = NoiseMap::new(width, height);

        let lon_extent = self.longitude_bounds.1 - self.longitude_bounds.0;
        let lat_extent = self.latitude_bounds.1 - self.latitude_bounds.0;

        let x_step = lon_extent / width as f64;
        let y_step = lat_extent / height as f64;

        for y in 0..height {
            let current_lat = self.latitude_bounds.0 + y_step * y as f64;

            for x in 0..width {
                let current_lon = self.longitude_bounds.0 + x_step * x as f64;

                let point = lat_lon_to_xyz(current_lat, current_lon);

                result_map[(x, y)] = self.source_module.get(point);
            }
        }

        result_map
    }
}

fn lat_lon_to_xyz(lat: f64, lon: f64) -> [f64; 3] {
    let r = lat.to_radians().cos();
    let x = r * lon.to_radians().cos();
    let y = lat.to_radians().sin();
    let z = r * lon.to_radians().sin();

    [x, y, z]
}
<commit_msg>Remove commented code<commit_after>use crate::{math::interpolate, noise_fns::NoiseFn, permutationtable::NoiseHasher, utils::noise_map::NoiseMap};

pub struct NoiseFnWrapper<NH, F, const DIM: usize>
where
    NH: NoiseHasher,
    F: Fn([f64; DIM], &NH) -> f64,
{
    hasher: NH,
    func: F,
}

impl<NH, F, const DIM: usize> NoiseFn<f64, DIM> for NoiseFnWrapper<NH, F, DIM>
where
    NH: NoiseHasher,
    F: Fn([f64; DIM], &NH) -> f64,
{
    fn get(&self, point: [f64; DIM]) -> f64 {
        (self.func)(point, &self.hasher)
    }
}

fn pad_array<const SIZE: usize>(values: &[f64]) -> [f64; SIZE] {
    let mut result = [0.0; SIZE];

    result[..values.len().min(SIZE)].clone_from_slice(&values[..values.len().min(SIZE)]);

    result
}

pub trait NoiseMapBuilder<SourceModule> {
    fn set_size(self, width: usize, height: usize) -> Self;

    fn set_source_module(self, source_module: SourceModule) -> Self;

    fn size(&self) -> (usize, usize);

    fn build(&self) -> NoiseMap;
}

pub struct CylinderMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    angle_bounds: (f64, f64),
    height_bounds: (f64, f64),
    size: (usize, usize),
    source_module: SourceModule,
}

impl<SourceModule> CylinderMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    pub fn new(source_module: SourceModule) -> Self {
        CylinderMapBuilder {
            angle_bounds: (-90.0, 90.0),
            height_bounds: (-1.0, 1.0),
            size: (100, 100),
            source_module,
        }
    }

    pub fn set_angle_bounds(self, lower_bound: f64, upper_bound: f64) -> Self {
        let angle_bounds = if lower_bound >= upper_bound {
            (upper_bound, lower_bound)
        } else {
            (lower_bound, upper_bound)
        };

        CylinderMapBuilder {
            angle_bounds,
            ..self
        }
    }

    pub fn set_height_bounds(self, lower_bound: f64, upper_bound: f64) -> Self {
        let height_bounds = if lower_bound >= upper_bound {
            (upper_bound, lower_bound)
        } else {
            (lower_bound, upper_bound)
        };

        CylinderMapBuilder {
            height_bounds,
            ..self
        }
    }

    pub fn angle_bounds(&self) -> (f64, f64) {
        self.angle_bounds
    }

    pub fn height_bounds(&self) -> (f64, f64) {
        self.height_bounds
    }
}

impl<SourceModule> NoiseMapBuilder<SourceModule> for CylinderMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    fn set_size(self, width: usize, height: usize) -> Self {
        CylinderMapBuilder {
            size: (width, height),
            ..self
        }
    }

    fn set_source_module(self, source_module: SourceModule) -> Self {
        CylinderMapBuilder {
            source_module,
            ..self
        }
    }

    fn size(&self) -> (usize, usize) {
        self.size
    }

    fn build(&self) -> NoiseMap {
        let mut result_map = NoiseMap::new(self.size.0, self.size.1);

        let (width, height) = self.size;

        let angle_extent = self.angle_bounds.1 - self.angle_bounds.0;
        let height_extent = self.height_bounds.1 - self.height_bounds.0;

        let x_step = angle_extent / width as f64;
        let y_step = height_extent / height as f64;

        for y in 0..height {
            let current_height = self.height_bounds.0 + y_step * y as f64;

            for x in 0..width {
                let current_angle = self.angle_bounds.0 + x_step * x as f64;

                let point_x = current_angle.to_radians().cos();
                let point_z = current_angle.to_radians().sin();

                let value = self.source_module.get([point_x, current_height, point_z]);

                result_map[(x, y)] = value;
            }
        }

        result_map
    }
}

pub struct PlaneMapBuilder<SourceModule, const DIM: usize>
where
    SourceModule: NoiseFn<f64, DIM>,
{
    is_seamless: bool,
    x_bounds: (f64, f64),
    y_bounds: (f64, f64),
    size: (usize, usize),
    source_module: SourceModule,
}

impl<NH, F, const DIM: usize> PlaneMapBuilder<NoiseFnWrapper<NH, F, DIM>, DIM>
where
    NH: NoiseHasher + Clone,
    F: Fn([f64; DIM], &NH) -> f64,
{
    pub fn new_fn(func: F, hasher: &NH) -> Self {
        PlaneMapBuilder {
            is_seamless: false,
            x_bounds: (-1.0, 1.0),
            y_bounds: (-1.0, 1.0),
            size: (100, 100),
            source_module: NoiseFnWrapper {
                hasher: hasher.clone(),
                func,
            },
        }
    }
}

impl<SourceModule, const DIM: usize> PlaneMapBuilder<SourceModule, DIM>
where
    SourceModule: NoiseFn<f64, DIM>,
{
    pub fn new(source_module: SourceModule) -> Self {
        PlaneMapBuilder {
            is_seamless: false,
            x_bounds: (-1.0, 1.0),
            y_bounds: (-1.0, 1.0),
            size: (100, 100),
            source_module,
        }
    }

    pub fn set_is_seamless(self, is_seamless: bool) -> Self {
        PlaneMapBuilder {
            is_seamless,
            ..self
        }
    }

    pub fn set_x_bounds(self, lower_x_bound: f64, upper_x_bound: f64) -> Self {
        PlaneMapBuilder {
            x_bounds: (lower_x_bound, upper_x_bound),
            ..self
        }
    }

    pub fn set_y_bounds(self, lower_y_bound: f64, upper_y_bound: f64) -> Self {
        PlaneMapBuilder {
            y_bounds: (lower_y_bound, upper_y_bound),
            ..self
        }
    }

    pub fn x_bounds(&self) -> (f64, f64) {
        self.x_bounds
    }

    pub fn y_bounds(&self) -> (f64, f64) {
        self.y_bounds
    }
}

impl<SourceModule, const DIM: usize> NoiseMapBuilder<SourceModule> for PlaneMapBuilder<SourceModule, DIM>
where
    SourceModule: NoiseFn<f64, DIM>,
{
    fn set_size(self, width: usize, height: usize) -> Self {
        PlaneMapBuilder {
            size: (width, height),
            ..self
        }
    }

    fn set_source_module(self, source_module: SourceModule) -> Self {
        PlaneMapBuilder {
            source_module,
            ..self
        }
    }

    fn size(&self) -> (usize, usize) {
        self.size
    }

    fn build(&self) -> NoiseMap {
        let (width, height) = self.size;

        let mut result_map = NoiseMap::new(width, height);

        let x_extent = self.x_bounds.1 - self.x_bounds.0;
        let y_extent = self.y_bounds.1 - self.y_bounds.0;

        let x_step = x_extent / width as f64;
        let y_step = y_extent / height as f64;

        for y in 0..height {
            let current_y = self.y_bounds.0 + y_step * y as f64;

            for x in 0..width {
                let current_x = self.x_bounds.0 + x_step * x as f64;

                let final_value = if self.is_seamless {
                    let sw_value = self.source_module.get(pad_array(&[current_x, current_y]));
                    let se_value = self
                        .source_module
                        .get(pad_array(&[current_x + x_extent, current_y]));
                    let nw_value = self
                        .source_module
                        .get(pad_array(&[current_x, current_y + y_extent]));
                    let ne_value =
                        self.source_module
                            .get(pad_array(&[current_x + x_extent, current_y + y_extent]));

                    let x_blend = 1.0 - ((current_x - self.x_bounds.0) / x_extent);
                    let y_blend = 1.0 - ((current_y - self.y_bounds.0) / y_extent);

                    let y0 = interpolate::linear(sw_value, se_value, x_blend);
                    let y1 = interpolate::linear(nw_value, ne_value, x_blend);

                    interpolate::linear(y0, y1, y_blend)
                } else {
                    self.source_module.get(pad_array(&[current_x, current_y]))
                };

                result_map[(x, y)] = final_value;
            }
        }

        result_map
    }
}

pub struct SphereMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    latitude_bounds: (f64, f64),
    longitude_bounds: (f64, f64),
    size: (usize, usize),
    source_module: SourceModule,
}

impl<SourceModule> SphereMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    pub fn new(source_module: SourceModule) -> Self {
        SphereMapBuilder {
            latitude_bounds: (-1.0, 1.0),
            longitude_bounds: (-1.0, 1.0),
            size: (100, 100),
            source_module,
        }
    }

    pub fn set_latitude_bounds(self, min_lat_bound: f64, max_lat_bound: f64) -> Self {
        SphereMapBuilder {
            latitude_bounds: (min_lat_bound, max_lat_bound),
            ..self
        }
    }

    pub fn set_longitude_bounds(self, min_lon_bound: f64, max_lon_bound: f64) -> Self {
        SphereMapBuilder {
            longitude_bounds: (min_lon_bound, max_lon_bound),
            ..self
        }
    }

    pub fn set_bounds(
        self,
        min_lat_bound: f64,
        max_lat_bound: f64,
        min_lon_bound: f64,
        max_lon_bound: f64,
    ) -> Self {
        SphereMapBuilder {
            latitude_bounds: (min_lat_bound, max_lat_bound),
            longitude_bounds: (min_lon_bound, max_lon_bound),
            ..self
        }
    }

    pub fn latitude_bounds(&self) -> (f64, f64) {
        self.latitude_bounds
    }

    pub fn longitude_bounds(&self) -> (f64, f64) {
        self.longitude_bounds
    }
}

impl<SourceModule> NoiseMapBuilder<SourceModule> for SphereMapBuilder<SourceModule>
where
    SourceModule: NoiseFn<f64, 3>,
{
    fn set_size(self, width: usize, height: usize) -> Self {
        SphereMapBuilder {
            size: (width, height),
            ..self
        }
    }

    fn set_source_module(self, source_module: SourceModule) -> Self {
        SphereMapBuilder {
            source_module,
            ..self
        }
    }

    fn size(&self) -> (usize, usize) {
        self.size
    }

    fn build(&self) -> NoiseMap {
        let (width, height) = self.size;

        let mut result_map = NoiseMap::new(width, height);

        let lon_extent = self.longitude_bounds.1 - self.longitude_bounds.0;
        let lat_extent = self.latitude_bounds.1 - self.latitude_bounds.0;

        let x_step = lon_extent / width as f64;
        let y_step = lat_extent / height as f64;

        for y in 0..height {
            let current_lat = self.latitude_bounds.0 + y_step * y as f64;

            for x in 0..width {
                let current_lon = self.longitude_bounds.0 + x_step * x as f64;

                let point = lat_lon_to_xyz(current_lat, current_lon);

                result_map[(x, y)] = self.source_module.get(point);
            }
        }

        result_map
    }
}

fn lat_lon_to_xyz(lat: f64, lon: f64) -> [f64; 3] {
    let r = lat.to_radians().cos();
    let x = r * lon.to_radians().cos();
    let y = lat.to_radians().sin();
    let z = r * lon.to_radians().sin();

    [x, y, z]
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;
use std::mem;
use std::ptr;
use std::sync::Arc;
use smallvec::SmallVec;

use device::Device;
use format::FormatDesc;
use framebuffer::RenderPass;
use framebuffer::LayoutAttachmentDescription;
use framebuffer::LayoutPassDescription;
use framebuffer::LayoutPassDependencyDescription;
use image::traits::Image;
use image::traits::ImageView;

use Error;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Defines the layout of multiple subpasses.
pub struct UnsafeRenderPass {
    renderpass: vk::RenderPass,
    device: Arc<Device>,
}

impl UnsafeRenderPass {
    /// Builds a new renderpass.
    ///
    /// # Safety
    ///
    /// This function doesn't check whether all the restrictions in the attachments, passes and
    /// passes dependencies were enforced.
    ///
    /// See the documentation of the structs of this module for more info about these restrictions.
    ///
    /// # Panic
    ///
    /// - Can panick if it detects some violations in the restrictions. Only unexpensive checks are
    /// performed. `debug_assert!` is used, so some restrictions are only checked in debug
    /// mode.
    ///
    pub unsafe fn new<Ia, Ip, Id>(device: &Arc<Device>, attachments: Ia, passes: Ip,
                                  pass_dependencies: Id)
                                  -> Result<UnsafeRenderPass, RenderPassCreationError>
        where Ia: ExactSizeIterator<Item = LayoutAttachmentDescription> + Clone,        // with specialization we can handle the "Clone" restriction internally
              Ip: ExactSizeIterator<Item = LayoutPassDescription> + Clone,      // with specialization we can handle the "Clone" restriction internally
              Id: ExactSizeIterator<Item = LayoutPassDependencyDescription>
    {
        let vk = device.pointers();

        // TODO: check the validity of the renderpass layout with debug_assert!
        //   - If the first use of an attachment in this render pass is as an input attachment, and the attachment is not also used as a color or depth/stencil attachment in the same subpass, then loadOp must not be VK_ATTACHMENT_LOAD_OP_CLEAR

        let attachments = attachments.clone().map(|attachment| {
            debug_assert!(attachment.samples.is_power_of_two());

            vk::AttachmentDescription {
                flags: 0,       // FIXME: may alias flag
                format: attachment.format as u32,
                samples: attachment.samples,
                loadOp: attachment.load as u32,
                storeOp: attachment.store as u32,
                stencilLoadOp: attachment.load as u32,       // TODO: allow user to choose
                stencilStoreOp: attachment.store as u32,      // TODO: allow user to choose
                initialLayout: attachment.initial_layout as u32,
                finalLayout: attachment.final_layout as u32,
            }
        }).collect::<SmallVec<[_; 16]>>();

        // We need to pass pointers to vkAttachmentReference structs when creating the renderpass.
        // Therefore we need to allocate them in advance.
        //
        // This block allocates, for each pass, in order, all color attachment references, then all
        // input attachment references, then all resolve attachment references, then the depth
        // stencil attachment reference.
        let attachment_references = passes.clone().flat_map(|pass| {
            // Performing some validation with debug asserts.
            debug_assert!(pass.resolve_attachments.is_empty() ||
                          pass.resolve_attachments.len() == pass.color_attachments.len());
            debug_assert!(pass.resolve_attachments.iter().all(|a| {
                              attachments[a.0].samples == 1
                          }));
            debug_assert!(pass.resolve_attachments.is_empty() ||
                          pass.color_attachments.iter().all(|a| {
                              attachments[a.0].samples > 1
                          }));
            debug_assert!(pass.resolve_attachments.is_empty() ||
                          pass.resolve_attachments.iter().zip(pass.color_attachments.iter())
                              .all(|(r, c)| {
                                  attachments[r.0].format == attachments[c.0].format
                              }));
            debug_assert!(pass.color_attachments.iter().cloned()
                              .chain(pass.depth_stencil.clone().into_iter())
                              .chain(pass.input_attachments.iter().cloned())
                              .chain(pass.resolve_attachments.iter().cloned())
                              .all(|(a, _)| {
                                  pass.preserve_attachments.iter().find(|&&b| a == b).is_none()
                              }));
            debug_assert!(pass.color_attachments.iter().cloned()
                              .chain(pass.depth_stencil.clone().into_iter())
                              .all(|(atch, layout)| {
                                  if let Some(r) = pass.input_attachments.iter()
                                                                         .find(|r| r.0 == atch)
                                  {
                                      r.1 == layout
                                  } else {
                                      true
                                  }
                              }));

            let resolve = pass.resolve_attachments.into_iter().map(|(offset, img_la)| {
                debug_assert!(offset < attachments.len());
                vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
            });

            let color = pass.color_attachments.into_iter().map(|(offset, img_la)| {
                debug_assert!(offset < attachments.len());
                vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
            });

            let input = pass.input_attachments.into_iter().map(|(offset, img_la)| {
                debug_assert!(offset < attachments.len());
                vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
            });

            let depthstencil = if let Some((offset, img_la)) = pass.depth_stencil {
                Some(vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, })
            } else {
                None
            }.into_iter();

            color.chain(input).chain(resolve).chain(depthstencil)
        }).collect::<SmallVec<[_; 16]>>();

        // Same as `attachment_references` but only for the preserve attachments.
        // This is separate because attachment references are u32s and not `vkAttachmentReference`
        // structs.
        let preserve_attachments_references = passes.clone().flat_map(|pass| {
            pass.preserve_attachments.into_iter().map(|offset| offset as u32)
        }).collect::<SmallVec<[_; 16]>>();

        // Now iterating over passes.
        let passes = {
            // `ref_index` and `preserve_ref_index` are increased during the loop and point to the
            // next element to use in respectively `attachment_references` and
            // `preserve_attachments_references`.
            let mut ref_index = 0usize;
            let mut preserve_ref_index = 0usize;
            let mut out: SmallVec<[_; 16]> = SmallVec::new();

            for pass in passes.clone() {
                if pass.color_attachments.len() as u32 >
                   device.physical_device().limits().max_color_attachments()
                {
                    return Err(RenderPassCreationError::ColorAttachmentsLimitExceeded);
                }

                let color_attachments = attachment_references.as_ptr().offset(ref_index as isize);
                ref_index += pass.color_attachments.len();
                let input_attachments = attachment_references.as_ptr().offset(ref_index as isize);
                ref_index += pass.input_attachments.len();
                let resolve_attachments = attachment_references.as_ptr().offset(ref_index as isize);
                ref_index += pass.resolve_attachments.len();
                let depth_stencil = if pass.depth_stencil.is_some() {
                    let a = attachment_references.as_ptr().offset(ref_index as isize);
                    ref_index += 1;
                    a
                } else {
                    ptr::null()
                };

                let preserve_attachments = preserve_attachments_references.as_ptr()
                                                              .offset(preserve_ref_index as isize);
                preserve_ref_index += pass.preserve_attachments.len();

                out.push(vk::SubpassDescription {
                    flags: 0,   // reserved
                    pipelineBindPoint: vk::PIPELINE_BIND_POINT_GRAPHICS,
                    inputAttachmentCount: pass.input_attachments.len() as u32,
                    pInputAttachments: if pass.input_attachments.is_empty() { ptr::null() }
                                       else { input_attachments },
                    colorAttachmentCount: pass.color_attachments.len() as u32,
                    pColorAttachments: if pass.color_attachments.is_empty() { ptr::null() }
                                       else { color_attachments },
                    pResolveAttachments: if pass.resolve_attachments.is_empty() { ptr::null() }
                                         else { resolve_attachments },
                    pDepthStencilAttachment: depth_stencil,
                    preserveAttachmentCount: pass.preserve_attachments.len() as u32,
                    pPreserveAttachments: if pass.preserve_attachments.is_empty() { ptr::null() }
                                          else { preserve_attachments },
                });
            }

            assert!(!out.is_empty());
            // If these assertions fails, there's a serious bug in the code above ^.
            debug_assert!(ref_index == attachment_references.len());
            debug_assert!(preserve_ref_index == preserve_attachments_references.len());

            out
        };

        let dependencies = pass_dependencies.map(|dependency| {
            debug_assert!(dependency.source_subpass < passes.len());
            debug_assert!(dependency.destination_subpass < passes.len());

            vk::SubpassDependency {
                srcSubpass: dependency.source_subpass as u32,
                dstSubpass: dependency.destination_subpass as u32,
                srcStageMask: vk::PIPELINE_STAGE_ALL_GRAPHICS_BIT,      // FIXME:
                dstStageMask: vk::PIPELINE_STAGE_ALL_GRAPHICS_BIT,      // FIXME:
                srcAccessMask: 0x0001FFFF,       // FIXME:
                dstAccessMask: 0x0001FFFF,       // FIXME:
                dependencyFlags: if dependency.by_region { vk::DEPENDENCY_BY_REGION_BIT } else { 0 },
            }
        }).collect::<SmallVec<[_; 16]>>();

        let renderpass = {
            let infos = vk::RenderPassCreateInfo {
                sType: vk::STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                attachmentCount: attachments.len() as u32,
                pAttachments: if attachments.is_empty() { ptr::null() }
                              else { attachments.as_ptr() },
                subpassCount: passes.len() as u32,
                pSubpasses: if passes.is_empty() { ptr::null() } else { passes.as_ptr() },
                dependencyCount: dependencies.len() as u32,
                pDependencies: if dependencies.is_empty() { ptr::null() }
                               else { dependencies.as_ptr() },
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateRenderPass(device.internal_object(), &infos,
                                                  ptr::null(), &mut output)));
            output
        };

        Ok(UnsafeRenderPass {
            device: device.clone(),
            renderpass: renderpass,
        })
    }

    /// Returns the device that was used to create this render pass.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl VulkanObject for UnsafeRenderPass {
    type Object = vk::RenderPass;

    #[inline]
    fn internal_object(&self) -> vk::RenderPass {
        self.renderpass
    }
}

unsafe impl RenderPass for UnsafeRenderPass {
    #[inline]
    fn render_pass(&self) -> &UnsafeRenderPass {
        self
    }
}

impl Drop for UnsafeRenderPass {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyRenderPass(self.device.internal_object(), self.renderpass, ptr::null());
        }
    }
}

/// Error that can happen when creating a compute pipeline.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RenderPassCreationError {
    /// Not enough memory.
    OomError(OomError),
    /// The maximum number of color attachments has been exceeded.
    ColorAttachmentsLimitExceeded,
}

impl error::Error for RenderPassCreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            RenderPassCreationError::OomError(_) => "not enough memory available",
            RenderPassCreationError::ColorAttachmentsLimitExceeded => {
                "the maximum number of color attachments has been exceeded"
            },
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            RenderPassCreationError::OomError(ref err) => Some(err),
            _ => None
        }
    }
}

impl fmt::Display for RenderPassCreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<OomError> for RenderPassCreationError {
    #[inline]
    fn from(err: OomError) -> RenderPassCreationError {
        RenderPassCreationError::OomError(err)
    }
}

impl From<Error> for RenderPassCreationError {
    #[inline]
    fn from(err: Error) -> RenderPassCreationError {
        match err {
            err @ Error::OutOfHostMemory => {
                RenderPassCreationError::OomError(OomError::from(err))
            },
            err @ Error::OutOfDeviceMemory => {
                RenderPassCreationError::OomError(OomError::from(err))
            },
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

#[cfg(test)]
mod tests {
    // TODO:
}
<commit_msg>Add test for too many color attachments<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;
use std::mem;
use std::ptr;
use std::sync::Arc;
use smallvec::SmallVec;

use device::Device;
use format::FormatDesc;
use framebuffer::RenderPass;
use framebuffer::LayoutAttachmentDescription;
use framebuffer::LayoutPassDescription;
use framebuffer::LayoutPassDependencyDescription;
use image::traits::Image;
use image::traits::ImageView;

use Error;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// Defines the layout of multiple subpasses.
pub struct UnsafeRenderPass {
    renderpass: vk::RenderPass,
    device: Arc<Device>,
}

impl UnsafeRenderPass {
    /// Builds a new renderpass.
    ///
    /// # Safety
    ///
    /// This function doesn't check whether all the restrictions in the attachments, passes and
    /// passes dependencies were enforced.
    ///
    /// See the documentation of the structs of this module for more info about these restrictions.
    ///
    /// # Panic
    ///
    /// - Can panick if it detects some violations in the restrictions. Only unexpensive checks are
    /// performed. `debug_assert!` is used, so some restrictions are only checked in debug
    /// mode.
    ///
    pub unsafe fn new<Ia, Ip, Id>(device: &Arc<Device>, attachments: Ia, passes: Ip,
                                  pass_dependencies: Id)
                                  -> Result<UnsafeRenderPass, RenderPassCreationError>
        where Ia: ExactSizeIterator<Item = LayoutAttachmentDescription> + Clone,        // with specialization we can handle the "Clone" restriction internally
              Ip: ExactSizeIterator<Item = LayoutPassDescription> + Clone,      // with specialization we can handle the "Clone" restriction internally
              Id: ExactSizeIterator<Item = LayoutPassDependencyDescription>
    {
        let vk = device.pointers();

        // TODO: check the validity of the renderpass layout with debug_assert!
        //   - If the first use of an attachment in this render pass is as an input attachment, and the attachment is not also used as a color or depth/stencil attachment in the same subpass, then loadOp must not be VK_ATTACHMENT_LOAD_OP_CLEAR

        let attachments = attachments.clone().map(|attachment| {
            debug_assert!(attachment.samples.is_power_of_two());

            vk::AttachmentDescription {
                flags: 0,       // FIXME: may alias flag
                format: attachment.format as u32,
                samples: attachment.samples,
                loadOp: attachment.load as u32,
                storeOp: attachment.store as u32,
                stencilLoadOp: attachment.load as u32,       // TODO: allow user to choose
                stencilStoreOp: attachment.store as u32,      // TODO: allow user to choose
                initialLayout: attachment.initial_layout as u32,
                finalLayout: attachment.final_layout as u32,
            }
        }).collect::<SmallVec<[_; 16]>>();

        // We need to pass pointers to vkAttachmentReference structs when creating the renderpass.
        // Therefore we need to allocate them in advance.
        //
        // This block allocates, for each pass, in order, all color attachment references, then all
        // input attachment references, then all resolve attachment references, then the depth
        // stencil attachment reference.
        let attachment_references = passes.clone().flat_map(|pass| {
            // Performing some validation with debug asserts.
            debug_assert!(pass.resolve_attachments.is_empty() ||
                          pass.resolve_attachments.len() == pass.color_attachments.len());
            debug_assert!(pass.resolve_attachments.iter().all(|a| {
                              attachments[a.0].samples == 1
                          }));
            debug_assert!(pass.resolve_attachments.is_empty() ||
                          pass.color_attachments.iter().all(|a| {
                              attachments[a.0].samples > 1
                          }));
            debug_assert!(pass.resolve_attachments.is_empty() ||
                          pass.resolve_attachments.iter().zip(pass.color_attachments.iter())
                              .all(|(r, c)| {
                                  attachments[r.0].format == attachments[c.0].format
                              }));
            debug_assert!(pass.color_attachments.iter().cloned()
                              .chain(pass.depth_stencil.clone().into_iter())
                              .chain(pass.input_attachments.iter().cloned())
                              .chain(pass.resolve_attachments.iter().cloned())
                              .all(|(a, _)| {
                                  pass.preserve_attachments.iter().find(|&&b| a == b).is_none()
                              }));
            debug_assert!(pass.color_attachments.iter().cloned()
                              .chain(pass.depth_stencil.clone().into_iter())
                              .all(|(atch, layout)| {
                                  if let Some(r) = pass.input_attachments.iter()
                                                                         .find(|r| r.0 == atch)
                                  {
                                      r.1 == layout
                                  } else {
                                      true
                                  }
                              }));

            let resolve = pass.resolve_attachments.into_iter().map(|(offset, img_la)| {
                debug_assert!(offset < attachments.len());
                vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
            });

            let color = pass.color_attachments.into_iter().map(|(offset, img_la)| {
                debug_assert!(offset < attachments.len());
                vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
            });

            let input = pass.input_attachments.into_iter().map(|(offset, img_la)| {
                debug_assert!(offset < attachments.len());
                vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
            });

            let depthstencil = if let Some((offset, img_la)) = pass.depth_stencil {
                Some(vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, })
            } else {
                None
            }.into_iter();

            color.chain(input).chain(resolve).chain(depthstencil)
        }).collect::<SmallVec<[_; 16]>>();

        // Same as `attachment_references` but only for the preserve attachments.
        // This is separate because attachment references are u32s and not `vkAttachmentReference`
        // structs.
        let preserve_attachments_references = passes.clone().flat_map(|pass| {
            pass.preserve_attachments.into_iter().map(|offset| offset as u32)
        }).collect::<SmallVec<[_; 16]>>();

        // Now iterating over passes.
        let passes = {
            // `ref_index` and `preserve_ref_index` are increased during the loop and point to the
            // next element to use in respectively `attachment_references` and
            // `preserve_attachments_references`.
            let mut ref_index = 0usize;
            let mut preserve_ref_index = 0usize;
            let mut out: SmallVec<[_; 16]> = SmallVec::new();

            for pass in passes.clone() {
                if pass.color_attachments.len() as u32 >
                   device.physical_device().limits().max_color_attachments()
                {
                    return Err(RenderPassCreationError::ColorAttachmentsLimitExceeded);
                }

                let color_attachments = attachment_references.as_ptr().offset(ref_index as isize);
                ref_index += pass.color_attachments.len();
                let input_attachments = attachment_references.as_ptr().offset(ref_index as isize);
                ref_index += pass.input_attachments.len();
                let resolve_attachments = attachment_references.as_ptr().offset(ref_index as isize);
                ref_index += pass.resolve_attachments.len();
                let depth_stencil = if pass.depth_stencil.is_some() {
                    let a = attachment_references.as_ptr().offset(ref_index as isize);
                    ref_index += 1;
                    a
                } else {
                    ptr::null()
                };

                let preserve_attachments = preserve_attachments_references.as_ptr()
                                                              .offset(preserve_ref_index as isize);
                preserve_ref_index += pass.preserve_attachments.len();

                out.push(vk::SubpassDescription {
                    flags: 0,   // reserved
                    pipelineBindPoint: vk::PIPELINE_BIND_POINT_GRAPHICS,
                    inputAttachmentCount: pass.input_attachments.len() as u32,
                    pInputAttachments: if pass.input_attachments.is_empty() { ptr::null() }
                                       else { input_attachments },
                    colorAttachmentCount: pass.color_attachments.len() as u32,
                    pColorAttachments: if pass.color_attachments.is_empty() { ptr::null() }
                                       else { color_attachments },
                    pResolveAttachments: if pass.resolve_attachments.is_empty() { ptr::null() }
                                         else { resolve_attachments },
                    pDepthStencilAttachment: depth_stencil,
                    preserveAttachmentCount: pass.preserve_attachments.len() as u32,
                    pPreserveAttachments: if pass.preserve_attachments.is_empty() { ptr::null() }
                                          else { preserve_attachments },
                });
            }

            assert!(!out.is_empty());
            // If these assertions fails, there's a serious bug in the code above ^.
            debug_assert!(ref_index == attachment_references.len());
            debug_assert!(preserve_ref_index == preserve_attachments_references.len());

            out
        };

        let dependencies = pass_dependencies.map(|dependency| {
            debug_assert!(dependency.source_subpass < passes.len());
            debug_assert!(dependency.destination_subpass < passes.len());

            vk::SubpassDependency {
                srcSubpass: dependency.source_subpass as u32,
                dstSubpass: dependency.destination_subpass as u32,
                srcStageMask: vk::PIPELINE_STAGE_ALL_GRAPHICS_BIT,      // FIXME:
                dstStageMask: vk::PIPELINE_STAGE_ALL_GRAPHICS_BIT,      // FIXME:
                srcAccessMask: 0x0001FFFF,       // FIXME:
                dstAccessMask: 0x0001FFFF,       // FIXME:
                dependencyFlags: if dependency.by_region { vk::DEPENDENCY_BY_REGION_BIT } else { 0 },
            }
        }).collect::<SmallVec<[_; 16]>>();

        let renderpass = {
            let infos = vk::RenderPassCreateInfo {
                sType: vk::STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                attachmentCount: attachments.len() as u32,
                pAttachments: if attachments.is_empty() { ptr::null() }
                              else { attachments.as_ptr() },
                subpassCount: passes.len() as u32,
                pSubpasses: if passes.is_empty() { ptr::null() } else { passes.as_ptr() },
                dependencyCount: dependencies.len() as u32,
                pDependencies: if dependencies.is_empty() { ptr::null() }
                               else { dependencies.as_ptr() },
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateRenderPass(device.internal_object(), &infos,
                                                  ptr::null(), &mut output)));
            output
        };

        Ok(UnsafeRenderPass {
            device: device.clone(),
            renderpass: renderpass,
        })
    }

    /// Returns the device that was used to create this render pass.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

unsafe impl VulkanObject for UnsafeRenderPass {
    type Object = vk::RenderPass;

    #[inline]
    fn internal_object(&self) -> vk::RenderPass {
        self.renderpass
    }
}

unsafe impl RenderPass for UnsafeRenderPass {
    #[inline]
    fn render_pass(&self) -> &UnsafeRenderPass {
        self
    }
}

impl Drop for UnsafeRenderPass {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyRenderPass(self.device.internal_object(), self.renderpass, ptr::null());
        }
    }
}

/// Error that can happen when creating a compute pipeline.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RenderPassCreationError {
    /// Not enough memory.
    OomError(OomError),
    /// The maximum number of color attachments has been exceeded.
    ColorAttachmentsLimitExceeded,
}

impl error::Error for RenderPassCreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            RenderPassCreationError::OomError(_) => "not enough memory available",
            RenderPassCreationError::ColorAttachmentsLimitExceeded => {
                "the maximum number of color attachments has been exceeded"
            },
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            RenderPassCreationError::OomError(ref err) => Some(err),
            _ => None
        }
    }
}

impl fmt::Display for RenderPassCreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<OomError> for RenderPassCreationError {
    #[inline]
    fn from(err: OomError) -> RenderPassCreationError {
        RenderPassCreationError::OomError(err)
    }
}

impl From<Error> for RenderPassCreationError {
    #[inline]
    fn from(err: Error) -> RenderPassCreationError {
        match err {
            err @ Error::OutOfHostMemory => {
                RenderPassCreationError::OomError(OomError::from(err))
            },
            err @ Error::OutOfDeviceMemory => {
                RenderPassCreationError::OomError(OomError::from(err))
            },
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

#[cfg(test)]
mod tests {
    use format::R8G8B8A8Unorm;
    use framebuffer::RenderPassCreationError;

    #[test]
    fn too_many_color_atch() {
        let (device, _) = gfx_dev_and_queue!();

        if device.physical_device().limits().max_color_attachments() >= 10 {
            return;     // test ignored
        }

        mod example {
            use format::R8G8B8A8Unorm;
            single_pass_renderpass! {
                attachments: {
                    a1: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a2: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a3: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a4: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a5: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a6: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a7: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a8: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a9: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, },
                    a10: { load: Clear, store: DontCare, format: R8G8B8A8Unorm, }
                },
                pass: {
                    color: [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10],
                    depth_stencil: {}
                }
            }
        }

        let formats = example::Formats {
            a1: (R8G8B8A8Unorm, 1), a2: (R8G8B8A8Unorm, 1), a3: (R8G8B8A8Unorm, 1),
            a4: (R8G8B8A8Unorm, 1), a5: (R8G8B8A8Unorm, 1), a6: (R8G8B8A8Unorm, 1),
            a7: (R8G8B8A8Unorm, 1), a8: (R8G8B8A8Unorm, 1), a9: (R8G8B8A8Unorm, 1),
            a10: (R8G8B8A8Unorm, 1),
        };

        match example::CustomRenderPass::new(&device, &formats) {
            Err(RenderPassCreationError::ColorAttachmentsLimitExceeded) => (),
            _ => panic!()
        }
    }
}
<|endoftext|>


<commit_before>pub fn factors(n: u32) -> Vec<u32> {
    unimplemented!("This should calculate the prime factors of {}", n)
}
<commit_msg>prime-factors: replace u32 with u64 in stub<commit_after>pub fn factors(n: u64) -> Vec<u64> {
    unimplemented!("This should calculate the prime factors of {}", n)
}
<|endoftext|>