1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use js_ffi::*;

pub enum ComputationGraphNode {
    Value(f32),
}

impl ComputationGraphNode {
    fn to_shader(&self) -> String {
        "function(){return 42;}".to_string()
    }
}

pub struct GPUKernel {
    gpu: JSObject,
    kernel: Option<JSObject>,
}

impl GPUKernel {
    pub fn new() -> Self {
        let api = globals::get::<GPU>();
        GPUKernel {
            gpu: api.create_gpu(),
            kernel: None,
        }
    }

    pub fn set_compute_graph(&mut self, node: ComputationGraphNode) {
        let api = globals::get::<GPU>();
        self.kernel = Some(api.create_kernel(&self.gpu, &node.to_shader()));
    }

    pub fn compute_2d(&mut self, width: u32, height: u32) -> JSObject {
        let api = globals::get::<GPU>();
        api.compute_2d(self.kernel.as_ref().unwrap(), width, height)
    }
}

struct GPU {
    fn_create_gpu: JSFunction,
    fn_create_kernel: JSFunction,
    fn_compute_2d: JSFunction,
}

impl Default for GPU {
    fn default() -> Self {
        GPU {
            fn_create_gpu: js!(
                () => {
                    debugger;
                    return new GPU();
                }
            ),
            fn_create_kernel: js!(
                (gpu,shader) => {
                    debugger;
                    return gpu.createKernel(function() {
                        return 42
                    }, { output: [3,3] });
                }
            ),
            fn_compute_2d: js!(
                (kernel,width,height) => {
                    debugger;
                    return kernel()
                }
            ),
        }
    }
}

impl GPU {
    fn create_gpu(&self) -> JSObject {
        JSObject(self.fn_create_gpu.invoke_0())
    }

    fn create_kernel(&self, gpu: &JSObject, shader: &str) -> JSObject {
        JSObject(self.fn_create_kernel.invoke_2(
            TYPE_OBJECT,
            gpu.as_js_value(),
            TYPE_STRING,
            to_js_string(shader),
        ))
    }

    fn compute_2d(&self, kernel: &JSObject, width: u32, height: u32) -> JSObject {
        JSObject(self.fn_compute_2d.invoke_3(
            TYPE_OBJECT,
            kernel.as_js_value(),
            TYPE_NUM,
            width.into(),
            TYPE_NUM,
            height.into(),
        ))
    }
}