1     object Vk =
2         val queue_family_ignored : u32 = 0xFFFFFFFF
3     
4     object ImageSubresourceRange =
5         val default = ImageSubresourceRange
6             aspect_mask = ImageAspectFlags/Color
7             base_mip_level = 0
8             level_count = 1
9             base_array_layer = 0
10            layer_count = 1
11    
12    object ImageMemoryBarrier =
13        val default = ImageMemoryBarrier
14            type = StructureType/ImageMemoryBarrier
15            next = null
16            src_access_mask = AccessFlags@zero
17            dst_access_mask = AccessFlags@zero
18            old_layout = ImageLayout/Undefined
19            new_layout = ImageLayout/Undefined
20            image = null
21            src_queue_family_index = Vk.queue_family_ignored
22            dst_queue_family_index = Vk.queue_family_ignored
23            subresource_range = ImageSubresourceRange.default
24    
25    def generate_mipmaps (physical_device : VkPhysicalDevice
26                          command_buffer : VkCommandBuffer
27                          image : VkImage
28                          image_format : VkFormat
29                          width : u32
30                          height : u32
31                          mip_levels : u32
32                          layer_count : u32) =
33        let mut format_properties = FormatProperties@zero
34        vk/get_physical_device_format_properties physical_device image_format
35                                                 format_properties@mut_ptr
36    
37        if not format_properties.optimal_tiling_features.contains
38                   FormatFeatureFlags/SampledImageFilterLinear
39        then
40            fail "image format does not support linear blitting"
41    
42        let mut barrier = ImageMemoryBarrier
43            =image
44            subresource_range = ImageSubresourceRange
45                =layer_count
46                f@ ImageSubresourceRange.default
47    
48            f@ ImageMemoryBarrier.default
49    
50        let mut mip_width = width as i32
51        let mut mip_height = height as i32
52    
53        for i = 1 until mip_levels do
54            barrier.subresource_range.base_mip_level = i - 1
55                    old_layout = ImageLayout/TransferDstOptimal
56                    new_layout = ImageLayout/TransferSrcOptimal
57                    src_access_mask = AccessFlags/TransferWrite
58                    dst_access_mask = AccessFlags/TransferRead
59    
60            vk/cmd_pipeline_barrier command_buffer PipelineStageFlags/Transfer
61                                    PipelineStageFlags/Transfer DependencyFlags@zero
62                                    0 null 0 null 1 barrier@ptr
63    
64            let blit = ImageBlit
65                src_offset1 = Offset3D.new
66                src_offset2 = Offset3D mip_width mip_height 1
67                src_subresource = ImageSubresourceLayers
68                    aspect_mask = ImageAspectFlags/Color
69                    mip_level = i - 1
70                    base_array_layer = 0
71                    layer_count = 1
72    
73                dst_offset1 = Offset3D.new
74                dst_offset2 = Offset3D
75                    x = if mip_width > 1 then mip_width / 2 else 1
76                    y = if mip_height > 1 then mip_height / 2 else 1
77                    z = 1
78    
79                dst_subresource = ImageSubresourceLayers
80                    aspect_mask = ImageAspectFlags/Color
81                    mip_level = i
82                    base_array_layer = 0
83                    layer_count = 1
84    
85            vk/cmd_blit_image command_buffer image ImageLayout/TransferSrcOptimal
86                              image ImageLayout/TransferDstOptimal 1 blit@ptr
87                              VkFilter/Linear
88    
89            barrier.old_layout = ImageLayout/TransferSrcOptimal
90                    new_layout = ImageLayout/ShaderReadOnlyOptimal
91                    src_access_mask = AccessFlags/TransferRead
92                    dst_access_mask = AccessFlags/ShaderRead
93    
94            vk/cmd_pipeline_barrier command_buffer PipelineStageFlags/Transfer
95                                    PipelineStageFlags/FragmentShader
96                                    DependencyFlags@zero 0 null 0 null 1 barrier@ptr
97    
98            if mip_height > 1 then
99                mip_height = mip_height / 2
100   
101           if mip_width > 1 then
102               mip_width = mip_width / 2
103   
104       barrier.subresource_range.base_mip_level = mip_levels - 1
105               old_layout = ImageLayout/TransferDstOptimal
106               new_layout = ImageLayout/ShaderReadOnlyOptimal
107               src_access_mask = AccessFlags/TransferWrite
108               dst_access_mask = AccessFlags/ShaderRead
109   
110       vk/cmd_pipeline_barrier command_buffer PipelineStageFlags/Transfer
111                               PipelineStageFlags/FragmentShader DependencyFlags@zero
112                               0 null 0 null 1 barrier@ptr
113