1     begin@ renderer
2     
3     type Pass =
4         val guard : Object -> bool
5         val objects = List<Object>.new
6         val object_ubos = List<ObjectUbo>.new
7         var object_buffer : StorageBuffer = null
8         var object_buffer_size : u32 = 0
9         var skin_buffer : StorageBuffer = null
10        var descriptor_set : DescriptorSet = null
11    
12    object Renderer
13        val copy_object_to_ubo = CompositeAction<(Object, mut ref ObjectUbo)>.new
14    
15    type Renderer @[mut local] =
16        val vulkan : Vulkan @auto
17        val size : mut Atom<Size> @mut
18        val cameras @[mut private] = List<Camera>.new
19        val camera : Camera
20        val passes : List<Pass>
21        var scene_ubo : SceneUbo
22        val scene_buffer : UniformBuffer
23        val skin_matrices = List<Matrix4>.new
24        var skin_buffer : StorageBuffer
25        var skin_buffer_size : u32
26        val skinned = List<Drawable>.new
27        val lighting : Lighting
28        val field : Field
29        val nodes : List<Node>
30        val cull_mode : CullModeFlags
31        val maybe_blit_image : Option<BlitImage>
32        let tokens = List<Token>.new
33    
34        def push_token (token : Token) =
35            tokens.add token
36    
37        def add self (camera : Camera) (object : Object) =
38            let index =
39                let maybe_index = self.cameras.try_index_of camera
40                case maybe_index of
41                    Some index -> index
42                    None ->
43                        self.cameras.add camera
44                        self.cameras.size - 1
45    
46            object.camera_index = index
47            for pass in self.passes do
48                if pass.guard object then
49                    pass.objects.add object
50    
51        def clear =
52            for pass in passes do
53                pass.objects.clear
54    
55            cameras.clear
56            skin_matrices.clear
57            skinned.clear
58    
59        local update_pass (pass_index : u32) =
60            let pass = passes[pass_index]
61            pass.object_ubos.clear
62            for object in pass.objects do
63                let mut ubo = ObjectUbo
64                    world = object.transform.transpose
65                    color = object.color
66                    emission = object.emission
67                    camera_index = object.camera_index
68                    aabb = object.aabb
69                    skin_offset = object.skin_offset
70    
71                Renderer.copy_object_to_ubo.invoke (object, ubo@mut_ref)
72                pass.object_ubos.add ubo
73    
74            let mut update_descriptor_set = false
75            let mut discard_descriptor_set = false
76            if pass.object_buffer == null
77               || pass.object_buffer_size < pass.object_ubos.size * sizeof ObjectUbo
78            then
79                if pass.object_buffer <> null then
80                    vulkan.unused_buffers.add pass.object_buffer
81                    discard_descriptor_set = true
82    
83                let buffer_size = pass.object_ubos.size * sizeof ObjectUbo
84                                  |> max Renderer.object_buffer_min_size
85                                  |> ceil_to_power_of_2
86    
87                pass.object_buffer = StorageBuffer.create buffer_size
88                pass.object_buffer_size = buffer_size
89                update_descriptor_set = true
90    
91            if pass.skin_buffer <> self.skin_buffer then
92                if pass.skin_buffer <> null then
93                    discard_descriptor_set = true
94    
95                update_descriptor_set = true
96                pass.skin_buffer = self.skin_buffer
97    
98            if discard_descriptor_set then
99                pass.descriptor_set.discard
100   
101           if update_descriptor_set then
102               pass.descriptor_set = DescriptorSet.create
103                   [self.scene_buffer.to_descriptor "scene"
104                    pass.object_buffer.to_descriptor "objects"
105                    pass.skin_buffer.to_descriptor "skins"]
106                   lighting.pipeline_layout[Renderer.scene_set]
107   
108           if pass.object_ubos.size > 0 then
109               pass.object_buffer.update pass.object_ubos.as_slice BarrierFlags/Raster
110