1     type ImageResources = struct
2         image : VkImage
3         view : VkImageView
4         framebuffer : VkFramebuffer
5     
6     type Swapchain =
7         val instance : Instance @auto
8         var width : u32
9         var height : u32
10        val format : VkFormat
11        val surface : VkSurface
12        val color_space : ColorSpaceKhr
13        var present_mode : PresentModeKhr
14        var image_index : u32 @mut
15        var image_count : u32 = 0
16        var render_pass : VkRenderPass
17        var swapchain : VkSwapchain
18        val image_resources = List<ImageResources>.new
19    
20        def update =
21            let device = instance.device
22            let physical_device = instance.physical_device
23    
24            if swapchain <> null then
25                vk/device_wait_idle device
26                for resources in image_resources do
27                    vk/destroy_framebuffer device resources.framebuffer null
28                    vk/destroy_image_view device resources.view null
29    
30                vk/destroy_render_pass device render_pass null
31                vk/destroy_swapchain_khr device swapchain null
32    
33            assert physical_device.is_supported instance.graphics_queue_family_index
34                                                surface
35    
36            let capabilities = physical_device.get_capabilities surface
37            let extent = if capabilities.current_extent.width == 0xFFFFFFFF then
38                let w = width.clamp capabilities.min_image_extent.width
39                                    capabilities.max_image_extent.width
40    
41                let h = height.clamp capabilities.min_image_extent.height
42                                     capabilities.max_image_extent.height
43    
44                Extent2D w h
45            else
46                capabilities.current_extent
47    
48            width = extent.width
49            height = extent.height
50    
51            present_mode = PresentModeKhr/FifoKhr
52            assert physical_device.get_present_modes surface
53                   |> contains present_mode
54    
55            let max_image_count = if capabilities.max_image_count > 0
56                                  then capabilities.max_image_count
57                                  else u32.max
58    
59            let min_image_count = 3
60                |> max capabilities.min_image_count
61                |> min max_image_count
62    
63            let pre_transform =
64                if capabilities.supported_transforms.contains
65                       SurfaceTransformFlagsKhr/IdentityKhr
66                then SurfaceTransformFlagsKhr/IdentityKhr
67                else capabilities.current_transform
68    
69            let composite_alpha =
70                [CompositeAlphaFlagsKhr/OpaqueKhr
71                 CompositeAlphaFlagsKhr/PreMultipliedKhr
72                 CompositeAlphaFlagsKhr/PostMultipliedKhr
73                 CompositeAlphaFlagsKhr/InheritKhr].as_slice
74                |> find { capabilities.supported_composite_alpha.contains _ }
75    
76            let swapchain_create_info = SwapchainCreateInfoKhr
77                type = StructureType/SwapchainCreateInfoKhr
78                next = null
79                flags = SwapchainCreateFlagsKhr@zero
80                =surface
81                =min_image_count
82                image_format = format
83                image_color_space = color_space
84                image_extent = extent
85                image_array_layers = 1
86                image_usage = ImageUsageFlags/ColorAttachment
87                image_sharing_mode = SharingMode/Exclusive
88                queue_family_index_count = 0
89                queue_family_indices = null
90                =pre_transform
91                =composite_alpha
92                =present_mode
93                clipped = 1
94                old_swapchain = null
95    
96            vk/create_swapchain_khr instance.device swapchain_create_info@ptr
97                                    null swapchain@mut_ptr
98            |> assert_success
99    
100           let images = device.get_images swapchain
101           assert image_resources.size == 0 || images.size == image_resources.size
102   
103           image_resources.clear
104           for image in images do
105               let color_view_create_info = ImageViewCreateInfo
106                   type = StructureType/ImageViewCreateInfo
107                   next = null
108                   flags = ImageViewCreateFlags@zero
109                   =image
110                   view_type = ViewType/2d
111                   =format
112                   components = ComponentMapping
113                       r = ComponentSwizzle/R
114                       g = ComponentSwizzle/G
115                       b = ComponentSwizzle/B
116                       a = ComponentSwizzle/A
117   
118                   subresource_range = ImageSubresourceRange
119                       aspect_mask = ImageAspectFlags/Color
120                       base_mip_level = 0
121                       level_count = 1
122                       base_array_layer = 0
123                       layer_count = 1
124   
125               let mut view = null
126               vk/create_image_view instance.device color_view_create_info@ptr
127                                    null view@mut_ptr
128               |> assert_success
129   
130               image_resources.add (ImageResources image view null)
131   
132           let attachment = AttachmentDescription
133               flags = AttachmentDescriptionFlags@zero
134               =format
135               samples = SampleCountFlags/1
136               load_op = AttachmentLoadOp/Clear
137               store_op = AttachmentStoreOp/Store
138               stencil_load_op = AttachmentLoadOp/DontCare
139               stencil_store_op = AttachmentStoreOp/DontCare
140               initial_layout = ImageLayout/Undefined
141               final_layout = ImageLayout/PresentSrcKhr
142   
143           let color_reference = AttachmentReference
144               attachment = 0
145               layout = ImageLayout/ColorAttachmentOptimal
146   
147           let subpass = SubpassDescription
148               flags = SubpassDescriptionFlags@zero
149               pipeline_bind_point = PipelineBindPoint/Graphics
150               input_attachment_count = 0
151               input_attachments = null
152               color_attachment_count = 1
153               color_attachments = color_reference@ptr
154               resolve_attachments = null
155               depth_stencil_attachment = null
156               preserve_attachment_count = 0
157               preserve_attachments = null
158   
159           let render_pass_create_info = RenderPassCreateInfo
160               type = StructureType/RenderPassCreateInfo
161               next = null
162               flags = RenderPassCreateFlags@zero
163               attachment_count = 1
164               attachments = attachment@ptr
165               subpass_count = 1
166               subpasses = subpass@ptr
167               dependency_count = 0
168               dependencies = null
169   
170           vk/create_render_pass instance.device render_pass_create_info@ptr
171                                 null render_pass@mut_ptr
172           |> assert_success
173   
174           for i = 0 until image_resources.size do
175               let framebuffer_create_info = FramebufferCreateInfo
176                   type = StructureType/FramebufferCreateInfo
177                   next = null
178                   flags = FramebufferCreateFlags@zero
179                   =render_pass
180                   attachment_count = 1
181                   attachments = image_resources[i].view@ptr
182                   =width
183                   =height
184                   layers = 1
185   
186               vk/create_framebuffer instance.device
187                                     framebuffer_create_info@ptr null
188                                     image_resources[i].framebuffer@mut_ptr
189               |> assert_success
190   
191           image_index = 0
192           image_count = images.size
193   
194   object Swapchain =
195       def create (surface : VkSurface
196                   width : u32
197                   height : u32) =
198           let swapchain = Swapchain
199               width height
200               format = VkFormat/B8G8R8A8_UNORM
201               =surface
202               color_space = ColorSpaceKhr/SrgbNonlinearKhr
203               present_mode = PresentModeKhr/ImmediateKhr
204               image_index = 0
205               render_pass = null
206               swapchain = null
207   
208           swapchain.update
209   
210           swapchain
211