xref: /aosp_15_r20/external/mesa3d/src/vulkan/runtime/vk_texcompress_astc.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* Copyright (c) 2017-2023 Hans-Kristian Arntzen
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be
12  * included in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "vk_texcompress_astc.h"
24 #include "util/texcompress_astc_luts_wrap.h"
25 #include "vk_alloc.h"
26 #include "vk_buffer.h"
27 #include "vk_device.h"
28 #include "vk_format.h"
29 #include "vk_image.h"
30 #include "vk_physical_device.h"
31 
32 /* type_indexes_mask bits are set/clear for support memory type index as per
33  * struct VkPhysicalDeviceMemoryProperties.memoryTypes[] */
34 static uint32_t
get_mem_type_index(struct vk_device * device,uint32_t type_indexes_mask,VkMemoryPropertyFlags mem_property)35 get_mem_type_index(struct vk_device *device, uint32_t type_indexes_mask,
36                    VkMemoryPropertyFlags mem_property)
37 {
38    const struct vk_physical_device_dispatch_table *disp = &device->physical->dispatch_table;
39    VkPhysicalDevice _phy_device = vk_physical_device_to_handle(device->physical);
40 
41    VkPhysicalDeviceMemoryProperties2 props2 = {
42       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2,
43       .pNext = NULL,
44    };
45    disp->GetPhysicalDeviceMemoryProperties2(_phy_device, &props2);
46 
47    for (uint32_t i = 0; i < props2.memoryProperties.memoryTypeCount; i++) {
48       if ((type_indexes_mask & (1 << i)) &&
49           ((props2.memoryProperties.memoryTypes[i].propertyFlags & mem_property) == mem_property)) {
50          return i;
51       }
52    }
53 
54    return -1;
55 }
56 
57 static VkResult
vk_create_buffer(struct vk_device * device,VkAllocationCallbacks * allocator,VkDeviceSize size,VkMemoryPropertyFlags mem_prop_flags,VkBufferUsageFlags usage_flags,VkBuffer * vk_buf,VkDeviceMemory * vk_mem)58 vk_create_buffer(struct vk_device *device, VkAllocationCallbacks *allocator,
59                  VkDeviceSize size, VkMemoryPropertyFlags mem_prop_flags,
60                  VkBufferUsageFlags usage_flags, VkBuffer *vk_buf,
61                  VkDeviceMemory *vk_mem)
62 {
63    VkResult result;
64    VkDevice _device = vk_device_to_handle(device);
65    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
66 
67    VkBufferCreateInfo buffer_create_info = {
68       .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
69       .size = size,
70       .usage = usage_flags,
71       .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
72    };
73    result =
74       disp->CreateBuffer(_device, &buffer_create_info, allocator, vk_buf);
75    if (unlikely(result != VK_SUCCESS))
76       return result;
77 
78    VkBufferMemoryRequirementsInfo2 mem_req_info = {
79       .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
80       .buffer = *vk_buf,
81    };
82    VkMemoryRequirements2 mem_req = {
83       .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
84    };
85    disp->GetBufferMemoryRequirements2(_device, &mem_req_info, &mem_req);
86 
87    uint32_t mem_type_index = get_mem_type_index(
88       device, mem_req.memoryRequirements.memoryTypeBits, mem_prop_flags);
89    if (mem_type_index == -1)
90       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
91 
92    VkMemoryAllocateInfo alloc_info = {
93       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
94       .allocationSize = mem_req.memoryRequirements.size,
95       .memoryTypeIndex = mem_type_index,
96    };
97    result = disp->AllocateMemory(_device, &alloc_info, allocator, vk_mem);
98    if (unlikely(result != VK_SUCCESS))
99       return result;
100 
101    disp->BindBufferMemory(_device, *vk_buf, *vk_mem, 0);
102 
103    return result;
104 }
105 
106 static VkResult
create_buffer_view(struct vk_device * device,VkAllocationCallbacks * allocator,VkBufferView * buf_view,VkBuffer buf,VkFormat format,VkDeviceSize size,VkDeviceSize offset)107 create_buffer_view(struct vk_device *device, VkAllocationCallbacks *allocator,
108                    VkBufferView *buf_view, VkBuffer buf, VkFormat format, VkDeviceSize size,
109                    VkDeviceSize offset)
110 {
111    VkResult result;
112    VkDevice _device = vk_device_to_handle(device);
113    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
114 
115    VkBufferViewCreateInfo buffer_view_create_info = {
116       .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
117       .buffer = buf,
118       .format = format,
119       .offset = offset,
120       .range = size,
121    };
122    result = disp->CreateBufferView(_device, &buffer_view_create_info,
123                                    allocator, buf_view);
124    return result;
125 }
126 
127 static uint8_t
get_partition_table_index(VkFormat format)128 get_partition_table_index(VkFormat format)
129 {
130    switch (format) {
131    case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
132    case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
133       return 0;
134    case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
135    case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
136       return 1;
137    case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
138    case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
139       return 2;
140    case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
141    case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
142       return 3;
143    case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
144    case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
145       return 4;
146    case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
147    case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
148       return 5;
149    case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
150    case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
151       return 6;
152    case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
153    case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
154       return 7;
155    case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
156    case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
157       return 8;
158    case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
159    case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
160       return 9;
161    case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
162    case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
163       return 10;
164    case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
165    case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
166       return 11;
167    case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
168    case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
169       return 12;
170    case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
171    case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
172       return 13;
173    default:
174       unreachable("bad astc format\n");
175       return 0;
176    }
177 }
178 
179 static VkResult
astc_prepare_buffer(struct vk_device * device,struct vk_texcompress_astc_state * astc,VkAllocationCallbacks * allocator,VkDeviceSize minTexelBufferOffsetAlignment,uint8_t * single_buf_ptr,VkDeviceSize * single_buf_size)180 astc_prepare_buffer(struct vk_device *device,
181                     struct vk_texcompress_astc_state *astc,
182                     VkAllocationCallbacks *allocator,
183                     VkDeviceSize minTexelBufferOffsetAlignment,
184                     uint8_t *single_buf_ptr,
185                     VkDeviceSize *single_buf_size)
186 {
187    VkResult result;
188    astc_decoder_lut_holder astc_lut_holder;
189    VkDeviceSize offset = 0;
190 
191    _mesa_init_astc_decoder_luts(&astc_lut_holder);
192 
193    const astc_decoder_lut *luts[] = {
194       &astc_lut_holder.color_endpoint,
195       &astc_lut_holder.color_endpoint_unquant,
196       &astc_lut_holder.weights,
197       &astc_lut_holder.weights_unquant,
198       &astc_lut_holder.trits_quints,
199    };
200 
201    for (unsigned i = 0; i < ARRAY_SIZE(luts); i++) {
202       offset = align(offset, minTexelBufferOffsetAlignment);
203       if (single_buf_ptr) {
204          memcpy(single_buf_ptr + offset, luts[i]->data, luts[i]->size_B);
205          result = create_buffer_view(device, allocator, &astc->luts_buf_view[i], astc->luts_buf,
206                                      vk_format_from_pipe_format(luts[i]->format), luts[i]->size_B,
207                                      offset);
208          if (result != VK_SUCCESS)
209             return result;
210       }
211       offset += luts[i]->size_B;
212    }
213 
214    const VkFormat formats[] = {
215       VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
216       VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
217       VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
218       VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
219       VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
220       VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
221       VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
222       VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
223       VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
224       VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
225       VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
226       VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
227       VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
228       VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
229    };
230 
231    for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++) {
232       unsigned lut_width;
233       unsigned lut_height;
234       const void *lut_data = _mesa_get_astc_decoder_partition_table(
235             vk_format_get_blockwidth(formats[i]),
236             vk_format_get_blockheight(formats[i]),
237             &lut_width, &lut_height);
238       const unsigned lut_size = lut_width * lut_height;
239 
240       offset = align(offset, minTexelBufferOffsetAlignment);
241       if (single_buf_ptr) {
242          memcpy(single_buf_ptr + offset, lut_data, lut_width * lut_height);
243 
244          result = create_buffer_view(device, allocator, &astc->partition_tbl_buf_view[i],
245                                      astc->luts_buf, VK_FORMAT_R8_UINT, lut_width * lut_height,
246                                      offset);
247          if (result != VK_SUCCESS)
248             return result;
249       }
250       offset += lut_size;
251    }
252 
253    *single_buf_size = offset;
254    return result;
255 }
256 
257 static VkResult
create_fill_all_luts_vulkan(struct vk_device * device,VkAllocationCallbacks * allocator,struct vk_texcompress_astc_state * astc)258 create_fill_all_luts_vulkan(struct vk_device *device,
259                             VkAllocationCallbacks *allocator,
260                             struct vk_texcompress_astc_state *astc)
261 {
262    VkResult result;
263    VkDevice _device = vk_device_to_handle(device);
264    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
265    VkPhysicalDevice _phy_device = vk_physical_device_to_handle(device->physical);
266    const struct vk_physical_device_dispatch_table *phy_disp = &device->physical->dispatch_table;
267    VkDeviceSize single_buf_size;
268    uint8_t *single_buf_ptr;
269 
270    VkPhysicalDeviceProperties2 phy_dev_prop = {
271       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
272       .pNext = NULL,
273    };
274    phy_disp->GetPhysicalDeviceProperties2(_phy_device, &phy_dev_prop);
275 
276    /* get the single_buf_size */
277    result = astc_prepare_buffer(device, astc, allocator,
278                                 phy_dev_prop.properties.limits.minTexelBufferOffsetAlignment,
279                                 NULL, &single_buf_size);
280 
281    /* create gpu buffer for all the luts */
282    result = vk_create_buffer(device, allocator, single_buf_size,
283                              VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
284                              VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
285                              VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
286                              &astc->luts_buf, &astc->luts_mem);
287    if (unlikely(result != VK_SUCCESS))
288       return result;
289 
290    disp->MapMemory(_device, astc->luts_mem, 0, VK_WHOLE_SIZE, 0, (void*)&single_buf_ptr);
291 
292    /* fill all the luts and create views */
293    result = astc_prepare_buffer(device, astc, allocator,
294                                 phy_dev_prop.properties.limits.minTexelBufferOffsetAlignment,
295                                 single_buf_ptr, &single_buf_size);
296 
297    disp->UnmapMemory(_device, astc->luts_mem);
298    return result;
299 }
300 
301 static VkResult
create_layout(struct vk_device * device,VkAllocationCallbacks * allocator,struct vk_texcompress_astc_state * astc)302 create_layout(struct vk_device *device, VkAllocationCallbacks *allocator,
303               struct vk_texcompress_astc_state *astc)
304 {
305    VkResult result;
306    VkDevice _device = vk_device_to_handle(device);
307    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
308 
309    VkDescriptorSetLayoutBinding bindings[] = {
310       {
311          .binding = 0, /* OutputImage2DArray */
312          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
313          .descriptorCount = 1,
314          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
315          .pImmutableSamplers = NULL,
316       },
317       {
318          .binding = 1, /* PayloadInput2DArray */
319          .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
320          .descriptorCount = 1,
321          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
322          .pImmutableSamplers = NULL,
323       },
324       {
325          .binding = 2, /* LUTRemainingBitsToEndpointQuantizer */
326          .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
327          .descriptorCount = 1,
328          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
329          .pImmutableSamplers = NULL,
330       },
331       {
332          .binding = 3, /* LUTEndpointUnquantize */
333          .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
334          .descriptorCount = 1,
335          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
336          .pImmutableSamplers = NULL,
337       },
338       {
339          .binding = 4, /* LUTWeightQuantizer */
340          .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
341          .descriptorCount = 1,
342          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
343          .pImmutableSamplers = NULL,
344       },
345       {
346          .binding = 5, /* LUTWeightUnquantize */
347          .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
348          .descriptorCount = 1,
349          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
350          .pImmutableSamplers = NULL,
351       },
352       {
353          .binding = 6, /* LUTTritQuintDecode */
354          .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
355          .descriptorCount = 1,
356          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
357          .pImmutableSamplers = NULL,
358       },
359       {
360          .binding = 7, /* LUTPartitionTable */
361          .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
362          .descriptorCount = 1,
363          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
364          .pImmutableSamplers = NULL,
365       },
366    };
367 
368    VkDescriptorSetLayoutCreateInfo ds_create_info = {
369       .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
370       .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
371       .bindingCount = ARRAY_SIZE(bindings),
372       .pBindings = bindings,
373    };
374 
375    result = disp->CreateDescriptorSetLayout(_device, &ds_create_info,
376                                             allocator, &astc->ds_layout);
377    if (result != VK_SUCCESS)
378       goto fail;
379 
380    VkPipelineLayoutCreateInfo pl_create_info = {
381       .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
382       .setLayoutCount = 1,
383       .pSetLayouts = &astc->ds_layout,
384       .pushConstantRangeCount = 1,
385       .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_COMPUTE_BIT, 0, 20},
386    };
387    result = disp->CreatePipelineLayout(_device, &pl_create_info, allocator,
388                                        &astc->p_layout);
389 fail:
390    return result;
391 }
392 
393 static const uint32_t astc_spv[] = {
394 #include "astc_spv.h"
395 };
396 
397 static VkResult
vk_astc_create_shader_module(struct vk_device * device,VkAllocationCallbacks * allocator,struct vk_texcompress_astc_state * astc)398 vk_astc_create_shader_module(struct vk_device *device,
399                              VkAllocationCallbacks *allocator,
400                              struct vk_texcompress_astc_state *astc)
401 {
402    VkDevice _device = vk_device_to_handle(device);
403    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
404 
405    VkShaderModuleCreateInfo shader_module_create_info = {
406       .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
407       .pNext = NULL,
408       .flags = 0,
409       .codeSize = sizeof(astc_spv),
410       .pCode = astc_spv,
411    };
412 
413    return disp->CreateShaderModule(_device, &shader_module_create_info,
414                                    allocator, &astc->shader_module);
415 }
416 
417 static VkResult
create_astc_decode_pipeline(struct vk_device * device,VkAllocationCallbacks * allocator,struct vk_texcompress_astc_state * astc,VkPipelineCache pipeline_cache,VkFormat format)418 create_astc_decode_pipeline(struct vk_device *device,
419                             VkAllocationCallbacks *allocator,
420                             struct vk_texcompress_astc_state *astc,
421                             VkPipelineCache pipeline_cache, VkFormat format)
422 {
423    VkResult result;
424    VkDevice _device = vk_device_to_handle(device);
425    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
426    VkPipeline pipeline;
427    uint8_t t_i;
428 
429    t_i = get_partition_table_index(format);
430 
431    uint32_t special_data[3] = {
432       vk_format_get_blockwidth(format),
433       vk_format_get_blockheight(format),
434       true,
435    };
436    VkSpecializationMapEntry special_map_entry[3] = {{
437                                                        .constantID = 0,
438                                                        .offset = 0,
439                                                        .size = 4,
440                                                     },
441                                                     {
442                                                        .constantID = 1,
443                                                        .offset = 4,
444                                                        .size = 4,
445                                                     },
446                                                     {
447                                                        .constantID = 2,
448                                                        .offset = 8,
449                                                        .size = 4,
450                                                     }};
451 
452    VkSpecializationInfo specialization_info = {
453       .mapEntryCount = 3,
454       .pMapEntries = special_map_entry,
455       .dataSize = 12,
456       .pData = special_data,
457    };
458 
459    /* compute shader */
460    VkPipelineShaderStageCreateInfo pipeline_shader_stage = {
461       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
462       .stage = VK_SHADER_STAGE_COMPUTE_BIT,
463       .module = astc->shader_module,
464       .pName = "main",
465       .pSpecializationInfo = &specialization_info,
466    };
467 
468    VkComputePipelineCreateInfo vk_pipeline_info = {
469       .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
470       .stage = pipeline_shader_stage,
471       .flags = 0,
472       .layout = astc->p_layout,
473    };
474 
475    result = disp->CreateComputePipelines(
476       _device, pipeline_cache, 1, &vk_pipeline_info, allocator, &pipeline);
477    if (result != VK_SUCCESS)
478       return result;
479 
480    astc->pipeline[t_i] = pipeline;
481    astc->pipeline_mask |= (1 << t_i);
482 
483    return result;
484 }
485 
486 VkPipeline
vk_texcompress_astc_get_decode_pipeline(struct vk_device * device,VkAllocationCallbacks * allocator,struct vk_texcompress_astc_state * astc,VkPipelineCache pipeline_cache,VkFormat format)487 vk_texcompress_astc_get_decode_pipeline(struct vk_device *device, VkAllocationCallbacks *allocator,
488                                         struct vk_texcompress_astc_state *astc, VkPipelineCache pipeline_cache,
489                                         VkFormat format)
490 {
491    VkResult result;
492    uint8_t t_i = get_partition_table_index(format);
493 
494    simple_mtx_lock(&astc->mutex);
495 
496    if (astc->pipeline[t_i])
497       goto unlock;
498 
499    if (!astc->shader_module) {
500       result = vk_astc_create_shader_module(device, allocator, astc);
501       if (result != VK_SUCCESS)
502          goto unlock;
503    }
504 
505    create_astc_decode_pipeline(device, allocator, astc, pipeline_cache, format);
506 
507 unlock:
508    simple_mtx_unlock(&astc->mutex);
509    return astc->pipeline[t_i];
510 }
511 
512 static inline void
fill_desc_image_info_struct(VkDescriptorImageInfo * info,VkImageView img_view,VkImageLayout img_layout)513 fill_desc_image_info_struct(VkDescriptorImageInfo *info, VkImageView img_view,
514                             VkImageLayout img_layout)
515 {
516    info->sampler = VK_NULL_HANDLE;
517    info->imageView = img_view;
518    info->imageLayout = img_layout;
519 }
520 
521 static inline void
fill_write_descriptor_set_image(VkWriteDescriptorSet * set,uint8_t bind_i,VkDescriptorType desc_type,VkDescriptorImageInfo * image_info)522 fill_write_descriptor_set_image(VkWriteDescriptorSet *set, uint8_t bind_i,
523                                 VkDescriptorType desc_type, VkDescriptorImageInfo *image_info)
524 {
525    set->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
526    set->pNext = NULL;
527    set->dstSet = VK_NULL_HANDLE;
528    set->dstBinding = bind_i;
529    set->dstArrayElement = 0;
530    set->descriptorCount = 1;
531    set->descriptorType = desc_type;
532    set->pImageInfo = image_info;
533    set->pBufferInfo = NULL;
534    set->pTexelBufferView = NULL;
535 }
536 
537 static inline void
fill_write_descriptor_set_uniform_texel(VkWriteDescriptorSet * set,uint8_t bind_i,VkBufferView * buf_view)538 fill_write_descriptor_set_uniform_texel(VkWriteDescriptorSet *set,
539                                         uint8_t bind_i,
540                                         VkBufferView *buf_view)
541 {
542    set->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
543    set->pNext = NULL;
544    set->dstSet = VK_NULL_HANDLE;
545    set->dstBinding = bind_i;
546    set->dstArrayElement = 0;
547    set->descriptorCount = 1;
548    set->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
549    set->pImageInfo = NULL;
550    set->pBufferInfo = NULL;
551    set->pTexelBufferView = buf_view;
552 }
553 
554 void
vk_texcompress_astc_fill_write_descriptor_sets(struct vk_texcompress_astc_state * astc,struct vk_texcompress_astc_write_descriptor_set * set,VkImageView src_img_view,VkImageLayout src_img_layout,VkImageView dst_img_view,VkFormat format)555 vk_texcompress_astc_fill_write_descriptor_sets(struct vk_texcompress_astc_state *astc,
556                                                struct vk_texcompress_astc_write_descriptor_set *set,
557                                                VkImageView src_img_view, VkImageLayout src_img_layout,
558                                                VkImageView dst_img_view,
559                                                VkFormat format)
560 {
561    unsigned desc_i;
562 
563    desc_i = 0;
564    fill_desc_image_info_struct(&set->dst_desc_image_info, dst_img_view, VK_IMAGE_LAYOUT_GENERAL);
565    fill_write_descriptor_set_image(&set->descriptor_set[desc_i], desc_i,
566                                    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &set->dst_desc_image_info);
567    desc_i++;
568    fill_desc_image_info_struct(&set->src_desc_image_info, src_img_view, src_img_layout);
569    fill_write_descriptor_set_image(&set->descriptor_set[desc_i], desc_i,
570                                    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &set->src_desc_image_info);
571    /* fill luts descriptor */
572    desc_i++;
573    for (unsigned i = 0; i < VK_TEXCOMPRESS_ASTC_NUM_LUTS; i++) {
574       fill_write_descriptor_set_uniform_texel(&set->descriptor_set[desc_i + i], desc_i + i,
575                                               &astc->luts_buf_view[i]);
576    }
577    desc_i += VK_TEXCOMPRESS_ASTC_NUM_LUTS;
578    uint8_t t_i = get_partition_table_index(format);
579    fill_write_descriptor_set_uniform_texel(&set->descriptor_set[desc_i], desc_i,
580                                            &astc->partition_tbl_buf_view[t_i]);
581    desc_i++;
582    assert(desc_i == ARRAY_SIZE(set->descriptor_set));
583 }
584 
585 VkResult
vk_texcompress_astc_init(struct vk_device * device,VkAllocationCallbacks * allocator,VkPipelineCache pipeline_cache,struct vk_texcompress_astc_state ** astc)586 vk_texcompress_astc_init(struct vk_device *device, VkAllocationCallbacks *allocator,
587                          VkPipelineCache pipeline_cache,
588                          struct vk_texcompress_astc_state **astc)
589 {
590    VkResult result;
591 
592    /* astc memory to be freed as part of vk_astc_decode_finish() */
593    *astc = vk_zalloc(allocator, sizeof(struct vk_texcompress_astc_state), 8,
594                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
595    if (*astc == NULL)
596       return VK_ERROR_OUT_OF_HOST_MEMORY;
597 
598    simple_mtx_init(&(*astc)->mutex, mtx_plain);
599 
600    result = create_fill_all_luts_vulkan(device, allocator, *astc);
601    if (result != VK_SUCCESS)
602       goto fail;
603 
604    result = create_layout(device, allocator, *astc);
605 
606 fail:
607    return result;
608 }
609 
610 void
vk_texcompress_astc_finish(struct vk_device * device,VkAllocationCallbacks * allocator,struct vk_texcompress_astc_state * astc)611 vk_texcompress_astc_finish(struct vk_device *device,
612                            VkAllocationCallbacks *allocator,
613                            struct vk_texcompress_astc_state *astc)
614 {
615    VkDevice _device = vk_device_to_handle(device);
616    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
617 
618    while (astc->pipeline_mask) {
619       uint8_t t_i = u_bit_scan(&astc->pipeline_mask);
620       disp->DestroyPipeline(_device, astc->pipeline[t_i], allocator);
621    }
622 
623    disp->DestroyPipelineLayout(_device, astc->p_layout, allocator);
624    disp->DestroyShaderModule(_device, astc->shader_module, allocator);
625    disp->DestroyDescriptorSetLayout(_device, astc->ds_layout, allocator);
626 
627    for (unsigned i = 0; i < VK_TEXCOMPRESS_ASTC_NUM_LUTS; i++)
628       disp->DestroyBufferView(_device, astc->luts_buf_view[i], allocator);
629 
630    for (unsigned i = 0; i < VK_TEXCOMPRESS_ASTC_NUM_PARTITION_TABLES; i++)
631       disp->DestroyBufferView(_device, astc->partition_tbl_buf_view[i], allocator);
632 
633    disp->DestroyBuffer(_device, astc->luts_buf, allocator);
634    disp->FreeMemory(_device, astc->luts_mem, allocator);
635 
636    vk_free(allocator, astc);
637 }
638