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