1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016 Red Hat. 3bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen 4bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 5bf215546Sopenharmony_ci */ 6bf215546Sopenharmony_ci 7bf215546Sopenharmony_ci/** 8bf215546Sopenharmony_ci * @file 9bf215546Sopenharmony_ci * 10bf215546Sopenharmony_ci * We use the bindless descriptor model, which maps fairly closely to how 11bf215546Sopenharmony_ci * Vulkan descriptor sets work. The two exceptions are input attachments and 12bf215546Sopenharmony_ci * dynamic descriptors, which have to be patched when recording command 13bf215546Sopenharmony_ci * buffers. We reserve an extra descriptor set for these. This descriptor set 14bf215546Sopenharmony_ci * contains all the input attachments in the pipeline, in order, and then all 15bf215546Sopenharmony_ci * the dynamic descriptors. The dynamic descriptors are stored in the CPU-side 16bf215546Sopenharmony_ci * datastructure for each tu_descriptor_set, and then combined into one big 17bf215546Sopenharmony_ci * descriptor set at CmdBindDescriptors time/draw time. 18bf215546Sopenharmony_ci */ 19bf215546Sopenharmony_ci 20bf215546Sopenharmony_ci#include "tu_descriptor_set.h" 21bf215546Sopenharmony_ci 22bf215546Sopenharmony_ci#include <fcntl.h> 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "util/mesa-sha1.h" 25bf215546Sopenharmony_ci#include "vk_descriptors.h" 26bf215546Sopenharmony_ci#include "vk_util.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "tu_device.h" 29bf215546Sopenharmony_ci#include "tu_image.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_cistatic inline uint8_t * 32bf215546Sopenharmony_cipool_base(struct tu_descriptor_pool *pool) 33bf215546Sopenharmony_ci{ 34bf215546Sopenharmony_ci return pool->host_bo ?: pool->bo->map; 35bf215546Sopenharmony_ci} 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistatic uint32_t 38bf215546Sopenharmony_cidescriptor_size(struct tu_device *dev, VkDescriptorType type) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci switch (type) { 41bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 42bf215546Sopenharmony_ci if (unlikely(dev->instance->debug_flags & TU_DEBUG_DYNAMIC)) 43bf215546Sopenharmony_ci return A6XX_TEX_CONST_DWORDS * 4; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci /* Input attachment doesn't use descriptor sets at all */ 46bf215546Sopenharmony_ci return 0; 47bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 48bf215546Sopenharmony_ci /* We make offsets and sizes all 16 dwords, to match how the hardware 49bf215546Sopenharmony_ci * interprets indices passed to sample/load/store instructions in 50bf215546Sopenharmony_ci * multiples of 16 dwords. This means that "normal" descriptors are all 51bf215546Sopenharmony_ci * of size 16, with padding for smaller descriptors like uniform storage 52bf215546Sopenharmony_ci * descriptors which are less than 16 dwords. However combined images 53bf215546Sopenharmony_ci * and samplers are actually two descriptors, so they have size 2. 54bf215546Sopenharmony_ci */ 55bf215546Sopenharmony_ci return A6XX_TEX_CONST_DWORDS * 4 * 2; 56bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 57bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 58bf215546Sopenharmony_ci /* When we support 16-bit storage, we need an extra descriptor setup as 59bf215546Sopenharmony_ci * a 32-bit array for isam to work. 60bf215546Sopenharmony_ci */ 61bf215546Sopenharmony_ci if (dev->physical_device->info->a6xx.storage_16bit) { 62bf215546Sopenharmony_ci return A6XX_TEX_CONST_DWORDS * 4 * 2; 63bf215546Sopenharmony_ci } else { 64bf215546Sopenharmony_ci return A6XX_TEX_CONST_DWORDS * 4; 65bf215546Sopenharmony_ci } 66bf215546Sopenharmony_ci default: 67bf215546Sopenharmony_ci return A6XX_TEX_CONST_DWORDS * 4; 68bf215546Sopenharmony_ci } 69bf215546Sopenharmony_ci} 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_cistatic bool 72bf215546Sopenharmony_ciis_dynamic(VkDescriptorType type) 73bf215546Sopenharmony_ci{ 74bf215546Sopenharmony_ci return type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC || 75bf215546Sopenharmony_ci type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_cistatic uint32_t 79bf215546Sopenharmony_cimutable_descriptor_size(struct tu_device *dev, const VkMutableDescriptorTypeListVALVE *list) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci uint32_t max_size = 0; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci for (uint32_t i = 0; i < list->descriptorTypeCount; i++) { 84bf215546Sopenharmony_ci uint32_t size = descriptor_size(dev, list->pDescriptorTypes[i]); 85bf215546Sopenharmony_ci max_size = MAX2(max_size, size); 86bf215546Sopenharmony_ci } 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci return max_size; 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 92bf215546Sopenharmony_citu_CreateDescriptorSetLayout( 93bf215546Sopenharmony_ci VkDevice _device, 94bf215546Sopenharmony_ci const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 95bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 96bf215546Sopenharmony_ci VkDescriptorSetLayout *pSetLayout) 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 99bf215546Sopenharmony_ci struct tu_descriptor_set_layout *set_layout; 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci assert(pCreateInfo->sType == 102bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO); 103bf215546Sopenharmony_ci const VkDescriptorSetLayoutBindingFlagsCreateInfo *variable_flags = 104bf215546Sopenharmony_ci vk_find_struct_const( 105bf215546Sopenharmony_ci pCreateInfo->pNext, 106bf215546Sopenharmony_ci DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO); 107bf215546Sopenharmony_ci const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info = 108bf215546Sopenharmony_ci vk_find_struct_const( 109bf215546Sopenharmony_ci pCreateInfo->pNext, 110bf215546Sopenharmony_ci MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci uint32_t num_bindings = 0; 113bf215546Sopenharmony_ci uint32_t immutable_sampler_count = 0; 114bf215546Sopenharmony_ci uint32_t ycbcr_sampler_count = 0; 115bf215546Sopenharmony_ci for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) { 116bf215546Sopenharmony_ci num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1); 117bf215546Sopenharmony_ci if ((pCreateInfo->pBindings[j].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 118bf215546Sopenharmony_ci pCreateInfo->pBindings[j].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) && 119bf215546Sopenharmony_ci pCreateInfo->pBindings[j].pImmutableSamplers) { 120bf215546Sopenharmony_ci immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci bool has_ycbcr_sampler = false; 123bf215546Sopenharmony_ci for (unsigned i = 0; i < pCreateInfo->pBindings[j].descriptorCount; ++i) { 124bf215546Sopenharmony_ci if (tu_sampler_from_handle(pCreateInfo->pBindings[j].pImmutableSamplers[i])->ycbcr_sampler) 125bf215546Sopenharmony_ci has_ycbcr_sampler = true; 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (has_ycbcr_sampler) 129bf215546Sopenharmony_ci ycbcr_sampler_count += pCreateInfo->pBindings[j].descriptorCount; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci } 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci uint32_t samplers_offset = 134bf215546Sopenharmony_ci offsetof(struct tu_descriptor_set_layout, binding[num_bindings]); 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci /* note: only need to store TEX_SAMP_DWORDS for immutable samples, 137bf215546Sopenharmony_ci * but using struct tu_sampler makes things simpler */ 138bf215546Sopenharmony_ci uint32_t size = samplers_offset + 139bf215546Sopenharmony_ci immutable_sampler_count * sizeof(struct tu_sampler) + 140bf215546Sopenharmony_ci ycbcr_sampler_count * sizeof(struct tu_sampler_ycbcr_conversion); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci set_layout = vk_object_zalloc(&device->vk, NULL, size, 143bf215546Sopenharmony_ci VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT); 144bf215546Sopenharmony_ci if (!set_layout) 145bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci set_layout->flags = pCreateInfo->flags; 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci /* We just allocate all the immutable samplers at the end of the struct */ 150bf215546Sopenharmony_ci struct tu_sampler *samplers = (void*) &set_layout->binding[num_bindings]; 151bf215546Sopenharmony_ci struct tu_sampler_ycbcr_conversion *ycbcr_samplers = 152bf215546Sopenharmony_ci (void*) &samplers[immutable_sampler_count]; 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci VkDescriptorSetLayoutBinding *bindings = NULL; 155bf215546Sopenharmony_ci VkResult result = vk_create_sorted_bindings( 156bf215546Sopenharmony_ci pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings); 157bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 158bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, set_layout); 159bf215546Sopenharmony_ci return vk_error(device, result); 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci set_layout->ref_cnt = 1; 163bf215546Sopenharmony_ci set_layout->binding_count = num_bindings; 164bf215546Sopenharmony_ci set_layout->shader_stages = 0; 165bf215546Sopenharmony_ci set_layout->has_immutable_samplers = false; 166bf215546Sopenharmony_ci set_layout->size = 0; 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci uint32_t dynamic_offset_size = 0; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) { 171bf215546Sopenharmony_ci const VkDescriptorSetLayoutBinding *binding = bindings + j; 172bf215546Sopenharmony_ci uint32_t b = binding->binding; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci set_layout->binding[b].type = binding->descriptorType; 175bf215546Sopenharmony_ci set_layout->binding[b].array_size = binding->descriptorCount; 176bf215546Sopenharmony_ci set_layout->binding[b].offset = set_layout->size; 177bf215546Sopenharmony_ci set_layout->binding[b].dynamic_offset_offset = dynamic_offset_size; 178bf215546Sopenharmony_ci set_layout->binding[b].shader_stages = binding->stageFlags; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci if (binding->descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) { 181bf215546Sopenharmony_ci /* For mutable descriptor types we must allocate a size that fits the 182bf215546Sopenharmony_ci * largest descriptor type that the binding can mutate to. 183bf215546Sopenharmony_ci */ 184bf215546Sopenharmony_ci set_layout->binding[b].size = 185bf215546Sopenharmony_ci mutable_descriptor_size(device, &mutable_info->pMutableDescriptorTypeLists[j]); 186bf215546Sopenharmony_ci } else { 187bf215546Sopenharmony_ci set_layout->binding[b].size = descriptor_size(device, binding->descriptorType); 188bf215546Sopenharmony_ci } 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci if (variable_flags && binding->binding < variable_flags->bindingCount && 191bf215546Sopenharmony_ci (variable_flags->pBindingFlags[binding->binding] & 192bf215546Sopenharmony_ci VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)) { 193bf215546Sopenharmony_ci assert(!binding->pImmutableSamplers); /* Terribly ill defined how 194bf215546Sopenharmony_ci many samplers are valid */ 195bf215546Sopenharmony_ci assert(binding->binding == num_bindings - 1); 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci set_layout->has_variable_descriptors = true; 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 201bf215546Sopenharmony_ci binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) && 202bf215546Sopenharmony_ci binding->pImmutableSamplers) { 203bf215546Sopenharmony_ci set_layout->binding[b].immutable_samplers_offset = samplers_offset; 204bf215546Sopenharmony_ci set_layout->has_immutable_samplers = true; 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci for (uint32_t i = 0; i < binding->descriptorCount; i++) 207bf215546Sopenharmony_ci samplers[i] = *tu_sampler_from_handle(binding->pImmutableSamplers[i]); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci samplers += binding->descriptorCount; 210bf215546Sopenharmony_ci samplers_offset += sizeof(struct tu_sampler) * binding->descriptorCount; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci bool has_ycbcr_sampler = false; 213bf215546Sopenharmony_ci for (unsigned i = 0; i < pCreateInfo->pBindings[j].descriptorCount; ++i) { 214bf215546Sopenharmony_ci if (tu_sampler_from_handle(binding->pImmutableSamplers[i])->ycbcr_sampler) 215bf215546Sopenharmony_ci has_ycbcr_sampler = true; 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci if (has_ycbcr_sampler) { 219bf215546Sopenharmony_ci set_layout->binding[b].ycbcr_samplers_offset = 220bf215546Sopenharmony_ci (const char*)ycbcr_samplers - (const char*)set_layout; 221bf215546Sopenharmony_ci for (uint32_t i = 0; i < binding->descriptorCount; i++) { 222bf215546Sopenharmony_ci struct tu_sampler *sampler = tu_sampler_from_handle(binding->pImmutableSamplers[i]); 223bf215546Sopenharmony_ci if (sampler->ycbcr_sampler) 224bf215546Sopenharmony_ci ycbcr_samplers[i] = *sampler->ycbcr_sampler; 225bf215546Sopenharmony_ci else 226bf215546Sopenharmony_ci ycbcr_samplers[i].ycbcr_model = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci ycbcr_samplers += binding->descriptorCount; 229bf215546Sopenharmony_ci } else { 230bf215546Sopenharmony_ci set_layout->binding[b].ycbcr_samplers_offset = 0; 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci if (is_dynamic(binding->descriptorType)) { 235bf215546Sopenharmony_ci dynamic_offset_size += 236bf215546Sopenharmony_ci binding->descriptorCount * set_layout->binding[b].size; 237bf215546Sopenharmony_ci } else { 238bf215546Sopenharmony_ci set_layout->size += 239bf215546Sopenharmony_ci binding->descriptorCount * set_layout->binding[b].size; 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci set_layout->shader_stages |= binding->stageFlags; 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci free(bindings); 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci set_layout->dynamic_offset_size = dynamic_offset_size; 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci *pSetLayout = tu_descriptor_set_layout_to_handle(set_layout); 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci return VK_SUCCESS; 252bf215546Sopenharmony_ci} 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 255bf215546Sopenharmony_citu_DestroyDescriptorSetLayout(VkDevice _device, 256bf215546Sopenharmony_ci VkDescriptorSetLayout _set_layout, 257bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 258bf215546Sopenharmony_ci{ 259bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 260bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set_layout, set_layout, _set_layout); 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci if (!set_layout) 263bf215546Sopenharmony_ci return; 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci tu_descriptor_set_layout_unref(device, set_layout); 266bf215546Sopenharmony_ci} 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_civoid 269bf215546Sopenharmony_citu_descriptor_set_layout_destroy(struct tu_device *device, 270bf215546Sopenharmony_ci struct tu_descriptor_set_layout *layout) 271bf215546Sopenharmony_ci{ 272bf215546Sopenharmony_ci assert(layout->ref_cnt == 0); 273bf215546Sopenharmony_ci vk_object_free(&device->vk, NULL, layout); 274bf215546Sopenharmony_ci} 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 277bf215546Sopenharmony_citu_GetDescriptorSetLayoutSupport( 278bf215546Sopenharmony_ci VkDevice _device, 279bf215546Sopenharmony_ci const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 280bf215546Sopenharmony_ci VkDescriptorSetLayoutSupport *pSupport) 281bf215546Sopenharmony_ci{ 282bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci VkDescriptorSetLayoutBinding *bindings = NULL; 285bf215546Sopenharmony_ci VkResult result = vk_create_sorted_bindings( 286bf215546Sopenharmony_ci pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings); 287bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 288bf215546Sopenharmony_ci pSupport->supported = false; 289bf215546Sopenharmony_ci return; 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci const VkDescriptorSetLayoutBindingFlagsCreateInfo *variable_flags = 293bf215546Sopenharmony_ci vk_find_struct_const( 294bf215546Sopenharmony_ci pCreateInfo->pNext, 295bf215546Sopenharmony_ci DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO); 296bf215546Sopenharmony_ci VkDescriptorSetVariableDescriptorCountLayoutSupport *variable_count = 297bf215546Sopenharmony_ci vk_find_struct( 298bf215546Sopenharmony_ci (void *) pCreateInfo->pNext, 299bf215546Sopenharmony_ci DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT); 300bf215546Sopenharmony_ci const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info = 301bf215546Sopenharmony_ci vk_find_struct_const( 302bf215546Sopenharmony_ci pCreateInfo->pNext, 303bf215546Sopenharmony_ci MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE); 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci if (variable_count) { 306bf215546Sopenharmony_ci variable_count->maxVariableDescriptorCount = 0; 307bf215546Sopenharmony_ci } 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci bool supported = true; 310bf215546Sopenharmony_ci uint64_t size = 0; 311bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { 312bf215546Sopenharmony_ci const VkDescriptorSetLayoutBinding *binding = bindings + i; 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci uint64_t descriptor_sz; 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci if (is_dynamic(binding->descriptorType)) { 317bf215546Sopenharmony_ci descriptor_sz = 0; 318bf215546Sopenharmony_ci } else if (binding->descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) { 319bf215546Sopenharmony_ci const VkMutableDescriptorTypeListVALVE *list = 320bf215546Sopenharmony_ci &mutable_info->pMutableDescriptorTypeLists[i]; 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci for (uint32_t j = 0; j < list->descriptorTypeCount; j++) { 323bf215546Sopenharmony_ci /* Don't support the input attachement and combined image sampler type 324bf215546Sopenharmony_ci * for mutable descriptors */ 325bf215546Sopenharmony_ci if (list->pDescriptorTypes[j] == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT || 326bf215546Sopenharmony_ci list->pDescriptorTypes[j] == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) { 327bf215546Sopenharmony_ci supported = false; 328bf215546Sopenharmony_ci goto out; 329bf215546Sopenharmony_ci } 330bf215546Sopenharmony_ci } 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci descriptor_sz = 333bf215546Sopenharmony_ci mutable_descriptor_size(device, &mutable_info->pMutableDescriptorTypeLists[i]); 334bf215546Sopenharmony_ci } else { 335bf215546Sopenharmony_ci descriptor_sz = descriptor_size(device, binding->descriptorType); 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci uint64_t descriptor_alignment = 8; 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci if (size && !ALIGN_POT(size, descriptor_alignment)) { 340bf215546Sopenharmony_ci supported = false; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci size = ALIGN_POT(size, descriptor_alignment); 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci uint64_t max_count = UINT64_MAX; 345bf215546Sopenharmony_ci if (descriptor_sz) 346bf215546Sopenharmony_ci max_count = (UINT64_MAX - size) / descriptor_sz; 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci if (max_count < binding->descriptorCount) { 349bf215546Sopenharmony_ci supported = false; 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci if (variable_flags && binding->binding < variable_flags->bindingCount && 353bf215546Sopenharmony_ci variable_count && 354bf215546Sopenharmony_ci (variable_flags->pBindingFlags[binding->binding] & 355bf215546Sopenharmony_ci VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)) { 356bf215546Sopenharmony_ci variable_count->maxVariableDescriptorCount = 357bf215546Sopenharmony_ci MIN2(UINT32_MAX, max_count); 358bf215546Sopenharmony_ci } 359bf215546Sopenharmony_ci size += binding->descriptorCount * descriptor_sz; 360bf215546Sopenharmony_ci } 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ciout: 363bf215546Sopenharmony_ci free(bindings); 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci pSupport->supported = supported; 366bf215546Sopenharmony_ci} 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci/* Note: we must hash any values used in tu_lower_io(). */ 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci#define SHA1_UPDATE_VALUE(ctx, x) _mesa_sha1_update(ctx, &(x), sizeof(x)); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_cistatic void 373bf215546Sopenharmony_cisha1_update_ycbcr_sampler(struct mesa_sha1 *ctx, 374bf215546Sopenharmony_ci const struct tu_sampler_ycbcr_conversion *sampler) 375bf215546Sopenharmony_ci{ 376bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, sampler->ycbcr_model); 377bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, sampler->ycbcr_range); 378bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, sampler->format); 379bf215546Sopenharmony_ci} 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_cistatic void 382bf215546Sopenharmony_cisha1_update_descriptor_set_binding_layout(struct mesa_sha1 *ctx, 383bf215546Sopenharmony_ci const struct tu_descriptor_set_binding_layout *layout, 384bf215546Sopenharmony_ci const struct tu_descriptor_set_layout *set_layout) 385bf215546Sopenharmony_ci{ 386bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->type); 387bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->offset); 388bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->size); 389bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->array_size); 390bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_offset); 391bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->immutable_samplers_offset); 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci const struct tu_sampler_ycbcr_conversion *ycbcr_samplers = 394bf215546Sopenharmony_ci tu_immutable_ycbcr_samplers(set_layout, layout); 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci if (ycbcr_samplers) { 397bf215546Sopenharmony_ci for (unsigned i = 0; i < layout->array_size; i++) 398bf215546Sopenharmony_ci sha1_update_ycbcr_sampler(ctx, ycbcr_samplers + i); 399bf215546Sopenharmony_ci } 400bf215546Sopenharmony_ci} 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_cistatic void 404bf215546Sopenharmony_cisha1_update_descriptor_set_layout(struct mesa_sha1 *ctx, 405bf215546Sopenharmony_ci const struct tu_descriptor_set_layout *layout) 406bf215546Sopenharmony_ci{ 407bf215546Sopenharmony_ci for (uint16_t i = 0; i < layout->binding_count; i++) 408bf215546Sopenharmony_ci sha1_update_descriptor_set_binding_layout(ctx, &layout->binding[i], 409bf215546Sopenharmony_ci layout); 410bf215546Sopenharmony_ci} 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci/* 413bf215546Sopenharmony_ci * Pipeline layouts. These have nothing to do with the pipeline. They are 414bf215546Sopenharmony_ci * just multiple descriptor set layouts pasted together. 415bf215546Sopenharmony_ci */ 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 418bf215546Sopenharmony_citu_CreatePipelineLayout(VkDevice _device, 419bf215546Sopenharmony_ci const VkPipelineLayoutCreateInfo *pCreateInfo, 420bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 421bf215546Sopenharmony_ci VkPipelineLayout *pPipelineLayout) 422bf215546Sopenharmony_ci{ 423bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 424bf215546Sopenharmony_ci struct tu_pipeline_layout *layout; 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci assert(pCreateInfo->sType == 427bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO); 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci layout = vk_object_alloc(&device->vk, pAllocator, sizeof(*layout), 430bf215546Sopenharmony_ci VK_OBJECT_TYPE_PIPELINE_LAYOUT); 431bf215546Sopenharmony_ci if (layout == NULL) 432bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci layout->num_sets = pCreateInfo->setLayoutCount; 435bf215546Sopenharmony_ci layout->dynamic_offset_size = 0; 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci unsigned dynamic_offset_size = 0; 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) { 440bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set_layout, set_layout, 441bf215546Sopenharmony_ci pCreateInfo->pSetLayouts[set]); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci assert(set < MAX_SETS); 444bf215546Sopenharmony_ci layout->set[set].layout = set_layout; 445bf215546Sopenharmony_ci layout->set[set].dynamic_offset_start = dynamic_offset_size; 446bf215546Sopenharmony_ci tu_descriptor_set_layout_ref(set_layout); 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci dynamic_offset_size += set_layout->dynamic_offset_size; 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci layout->dynamic_offset_size = dynamic_offset_size; 452bf215546Sopenharmony_ci layout->push_constant_size = 0; 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 455bf215546Sopenharmony_ci const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i; 456bf215546Sopenharmony_ci layout->push_constant_size = 457bf215546Sopenharmony_ci MAX2(layout->push_constant_size, range->offset + range->size); 458bf215546Sopenharmony_ci } 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci layout->push_constant_size = align(layout->push_constant_size, 16); 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci struct mesa_sha1 ctx; 463bf215546Sopenharmony_ci _mesa_sha1_init(&ctx); 464bf215546Sopenharmony_ci for (unsigned s = 0; s < layout->num_sets; s++) { 465bf215546Sopenharmony_ci sha1_update_descriptor_set_layout(&ctx, layout->set[s].layout); 466bf215546Sopenharmony_ci _mesa_sha1_update(&ctx, &layout->set[s].dynamic_offset_start, 467bf215546Sopenharmony_ci sizeof(layout->set[s].dynamic_offset_start)); 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci _mesa_sha1_update(&ctx, &layout->num_sets, sizeof(layout->num_sets)); 470bf215546Sopenharmony_ci _mesa_sha1_update(&ctx, &layout->push_constant_size, 471bf215546Sopenharmony_ci sizeof(layout->push_constant_size)); 472bf215546Sopenharmony_ci _mesa_sha1_final(&ctx, layout->sha1); 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci *pPipelineLayout = tu_pipeline_layout_to_handle(layout); 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci return VK_SUCCESS; 477bf215546Sopenharmony_ci} 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 480bf215546Sopenharmony_citu_DestroyPipelineLayout(VkDevice _device, 481bf215546Sopenharmony_ci VkPipelineLayout _pipelineLayout, 482bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 483bf215546Sopenharmony_ci{ 484bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 485bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_pipeline_layout, pipeline_layout, _pipelineLayout); 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci if (!pipeline_layout) 488bf215546Sopenharmony_ci return; 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci for (uint32_t i = 0; i < pipeline_layout->num_sets; i++) 491bf215546Sopenharmony_ci tu_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout); 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, pipeline_layout); 494bf215546Sopenharmony_ci} 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci#define EMPTY 1 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_cistatic VkResult 499bf215546Sopenharmony_citu_descriptor_set_create(struct tu_device *device, 500bf215546Sopenharmony_ci struct tu_descriptor_pool *pool, 501bf215546Sopenharmony_ci struct tu_descriptor_set_layout *layout, 502bf215546Sopenharmony_ci const uint32_t *variable_count, 503bf215546Sopenharmony_ci struct tu_descriptor_set **out_set) 504bf215546Sopenharmony_ci{ 505bf215546Sopenharmony_ci struct tu_descriptor_set *set; 506bf215546Sopenharmony_ci unsigned dynamic_offset = sizeof(struct tu_descriptor_set); 507bf215546Sopenharmony_ci unsigned mem_size = dynamic_offset + layout->dynamic_offset_size; 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci if (pool->host_memory_base) { 510bf215546Sopenharmony_ci if (pool->host_memory_end - pool->host_memory_ptr < mem_size) 511bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY); 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci set = (struct tu_descriptor_set*)pool->host_memory_ptr; 514bf215546Sopenharmony_ci pool->host_memory_ptr += mem_size; 515bf215546Sopenharmony_ci } else { 516bf215546Sopenharmony_ci set = vk_alloc2(&device->vk.alloc, NULL, mem_size, 8, 517bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci if (!set) 520bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci memset(set, 0, mem_size); 524bf215546Sopenharmony_ci vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci if (layout->dynamic_offset_size) { 527bf215546Sopenharmony_ci set->dynamic_descriptors = (uint32_t *)((uint8_t*)set + dynamic_offset); 528bf215546Sopenharmony_ci } 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci set->layout = layout; 531bf215546Sopenharmony_ci set->pool = pool; 532bf215546Sopenharmony_ci uint32_t layout_size = layout->size; 533bf215546Sopenharmony_ci if (variable_count) { 534bf215546Sopenharmony_ci assert(layout->has_variable_descriptors); 535bf215546Sopenharmony_ci uint32_t stride = layout->binding[layout->binding_count - 1].size; 536bf215546Sopenharmony_ci layout_size = layout->binding[layout->binding_count - 1].offset + 537bf215546Sopenharmony_ci *variable_count * stride; 538bf215546Sopenharmony_ci } 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci if (layout_size) { 541bf215546Sopenharmony_ci set->size = layout_size; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci if (!pool->host_memory_base && pool->entry_count == pool->max_entry_count) { 544bf215546Sopenharmony_ci vk_object_free(&device->vk, NULL, set); 545bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY); 546bf215546Sopenharmony_ci } 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci /* try to allocate linearly first, so that we don't spend 549bf215546Sopenharmony_ci * time looking for gaps if the app only allocates & 550bf215546Sopenharmony_ci * resets via the pool. */ 551bf215546Sopenharmony_ci if (pool->current_offset + layout_size <= pool->size) { 552bf215546Sopenharmony_ci set->mapped_ptr = (uint32_t*)(pool_base(pool) + pool->current_offset); 553bf215546Sopenharmony_ci set->va = pool->host_bo ? 0 : pool->bo->iova + pool->current_offset; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci if (!pool->host_memory_base) { 556bf215546Sopenharmony_ci pool->entries[pool->entry_count].offset = pool->current_offset; 557bf215546Sopenharmony_ci pool->entries[pool->entry_count].size = layout_size; 558bf215546Sopenharmony_ci pool->entries[pool->entry_count].set = set; 559bf215546Sopenharmony_ci pool->entry_count++; 560bf215546Sopenharmony_ci } 561bf215546Sopenharmony_ci pool->current_offset += layout_size; 562bf215546Sopenharmony_ci } else if (!pool->host_memory_base) { 563bf215546Sopenharmony_ci uint64_t offset = 0; 564bf215546Sopenharmony_ci int index; 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci for (index = 0; index < pool->entry_count; ++index) { 567bf215546Sopenharmony_ci if (pool->entries[index].offset - offset >= layout_size) 568bf215546Sopenharmony_ci break; 569bf215546Sopenharmony_ci offset = pool->entries[index].offset + pool->entries[index].size; 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci if (pool->size - offset < layout_size) { 573bf215546Sopenharmony_ci vk_object_free(&device->vk, NULL, set); 574bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY); 575bf215546Sopenharmony_ci } 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci set->mapped_ptr = (uint32_t*)(pool_base(pool) + offset); 578bf215546Sopenharmony_ci set->va = pool->host_bo ? 0 : pool->bo->iova + offset; 579bf215546Sopenharmony_ci 580bf215546Sopenharmony_ci memmove(&pool->entries[index + 1], &pool->entries[index], 581bf215546Sopenharmony_ci sizeof(pool->entries[0]) * (pool->entry_count - index)); 582bf215546Sopenharmony_ci pool->entries[index].offset = offset; 583bf215546Sopenharmony_ci pool->entries[index].size = layout_size; 584bf215546Sopenharmony_ci pool->entries[index].set = set; 585bf215546Sopenharmony_ci pool->entry_count++; 586bf215546Sopenharmony_ci } else 587bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY); 588bf215546Sopenharmony_ci } 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci if (layout->has_immutable_samplers) { 591bf215546Sopenharmony_ci for (unsigned i = 0; i < layout->binding_count; ++i) { 592bf215546Sopenharmony_ci if (!layout->binding[i].immutable_samplers_offset) 593bf215546Sopenharmony_ci continue; 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci unsigned offset = layout->binding[i].offset / 4; 596bf215546Sopenharmony_ci if (layout->binding[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 597bf215546Sopenharmony_ci offset += A6XX_TEX_CONST_DWORDS; 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci const struct tu_sampler *samplers = 600bf215546Sopenharmony_ci (const struct tu_sampler *)((const char *)layout + 601bf215546Sopenharmony_ci layout->binding[i].immutable_samplers_offset); 602bf215546Sopenharmony_ci for (unsigned j = 0; j < layout->binding[i].array_size; ++j) { 603bf215546Sopenharmony_ci memcpy(set->mapped_ptr + offset, samplers[j].descriptor, 604bf215546Sopenharmony_ci sizeof(samplers[j].descriptor)); 605bf215546Sopenharmony_ci offset += layout->binding[i].size / 4; 606bf215546Sopenharmony_ci } 607bf215546Sopenharmony_ci } 608bf215546Sopenharmony_ci } 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_ci tu_descriptor_set_layout_ref(layout); 611bf215546Sopenharmony_ci list_addtail(&set->pool_link, &pool->desc_sets); 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci *out_set = set; 614bf215546Sopenharmony_ci return VK_SUCCESS; 615bf215546Sopenharmony_ci} 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_cistatic void 618bf215546Sopenharmony_citu_descriptor_set_destroy(struct tu_device *device, 619bf215546Sopenharmony_ci struct tu_descriptor_pool *pool, 620bf215546Sopenharmony_ci struct tu_descriptor_set *set, 621bf215546Sopenharmony_ci bool free_bo) 622bf215546Sopenharmony_ci{ 623bf215546Sopenharmony_ci assert(!pool->host_memory_base); 624bf215546Sopenharmony_ci 625bf215546Sopenharmony_ci if (free_bo && set->size && !pool->host_memory_base) { 626bf215546Sopenharmony_ci uint32_t offset = (uint8_t*)set->mapped_ptr - pool_base(pool); 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci for (int i = 0; i < pool->entry_count; ++i) { 629bf215546Sopenharmony_ci if (pool->entries[i].offset == offset) { 630bf215546Sopenharmony_ci memmove(&pool->entries[i], &pool->entries[i+1], 631bf215546Sopenharmony_ci sizeof(pool->entries[i]) * (pool->entry_count - i - 1)); 632bf215546Sopenharmony_ci --pool->entry_count; 633bf215546Sopenharmony_ci break; 634bf215546Sopenharmony_ci } 635bf215546Sopenharmony_ci } 636bf215546Sopenharmony_ci } 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci vk_object_free(&device->vk, NULL, set); 639bf215546Sopenharmony_ci} 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 642bf215546Sopenharmony_citu_CreateDescriptorPool(VkDevice _device, 643bf215546Sopenharmony_ci const VkDescriptorPoolCreateInfo *pCreateInfo, 644bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 645bf215546Sopenharmony_ci VkDescriptorPool *pDescriptorPool) 646bf215546Sopenharmony_ci{ 647bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 648bf215546Sopenharmony_ci struct tu_descriptor_pool *pool; 649bf215546Sopenharmony_ci uint64_t size = sizeof(struct tu_descriptor_pool); 650bf215546Sopenharmony_ci uint64_t bo_size = 0, bo_count = 0, dynamic_size = 0; 651bf215546Sopenharmony_ci VkResult ret; 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info = 654bf215546Sopenharmony_ci vk_find_struct_const( pCreateInfo->pNext, 655bf215546Sopenharmony_ci MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE); 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) { 658bf215546Sopenharmony_ci if (pCreateInfo->pPoolSizes[i].type != VK_DESCRIPTOR_TYPE_SAMPLER) 659bf215546Sopenharmony_ci bo_count += pCreateInfo->pPoolSizes[i].descriptorCount; 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci switch(pCreateInfo->pPoolSizes[i].type) { 662bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 663bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 664bf215546Sopenharmony_ci dynamic_size += descriptor_size(device, pCreateInfo->pPoolSizes[i].type) * 665bf215546Sopenharmony_ci pCreateInfo->pPoolSizes[i].descriptorCount; 666bf215546Sopenharmony_ci break; 667bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE: 668bf215546Sopenharmony_ci if (mutable_info && i < mutable_info->mutableDescriptorTypeListCount && 669bf215546Sopenharmony_ci mutable_info->pMutableDescriptorTypeLists[i].descriptorTypeCount > 0) { 670bf215546Sopenharmony_ci bo_size += 671bf215546Sopenharmony_ci mutable_descriptor_size(device, &mutable_info->pMutableDescriptorTypeLists[i]) * 672bf215546Sopenharmony_ci pCreateInfo->pPoolSizes[i].descriptorCount; 673bf215546Sopenharmony_ci } else { 674bf215546Sopenharmony_ci /* Allocate the maximum size possible. */ 675bf215546Sopenharmony_ci bo_size += 2 * A6XX_TEX_CONST_DWORDS * 4 * 676bf215546Sopenharmony_ci pCreateInfo->pPoolSizes[i].descriptorCount; 677bf215546Sopenharmony_ci } 678bf215546Sopenharmony_ci continue; 679bf215546Sopenharmony_ci default: 680bf215546Sopenharmony_ci break; 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci bo_size += descriptor_size(device, pCreateInfo->pPoolSizes[i].type) * 684bf215546Sopenharmony_ci pCreateInfo->pPoolSizes[i].descriptorCount; 685bf215546Sopenharmony_ci } 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) { 688bf215546Sopenharmony_ci uint64_t host_size = pCreateInfo->maxSets * sizeof(struct tu_descriptor_set); 689bf215546Sopenharmony_ci host_size += sizeof(struct tu_bo*) * bo_count; 690bf215546Sopenharmony_ci host_size += dynamic_size; 691bf215546Sopenharmony_ci size += host_size; 692bf215546Sopenharmony_ci } else { 693bf215546Sopenharmony_ci size += sizeof(struct tu_descriptor_pool_entry) * pCreateInfo->maxSets; 694bf215546Sopenharmony_ci } 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci pool = vk_object_zalloc(&device->vk, pAllocator, size, 697bf215546Sopenharmony_ci VK_OBJECT_TYPE_DESCRIPTOR_POOL); 698bf215546Sopenharmony_ci if (!pool) 699bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) { 702bf215546Sopenharmony_ci pool->host_memory_base = (uint8_t*)pool + sizeof(struct tu_descriptor_pool); 703bf215546Sopenharmony_ci pool->host_memory_ptr = pool->host_memory_base; 704bf215546Sopenharmony_ci pool->host_memory_end = (uint8_t*)pool + size; 705bf215546Sopenharmony_ci } 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci if (bo_size) { 708bf215546Sopenharmony_ci if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE)) { 709bf215546Sopenharmony_ci ret = tu_bo_init_new(device, &pool->bo, bo_size, TU_BO_ALLOC_ALLOW_DUMP); 710bf215546Sopenharmony_ci if (ret) 711bf215546Sopenharmony_ci goto fail_alloc; 712bf215546Sopenharmony_ci 713bf215546Sopenharmony_ci ret = tu_bo_map(device, pool->bo); 714bf215546Sopenharmony_ci if (ret) 715bf215546Sopenharmony_ci goto fail_map; 716bf215546Sopenharmony_ci } else { 717bf215546Sopenharmony_ci pool->host_bo = vk_alloc2(&device->vk.alloc, pAllocator, bo_size, 8, 718bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 719bf215546Sopenharmony_ci if (!pool->host_bo) { 720bf215546Sopenharmony_ci ret = VK_ERROR_OUT_OF_HOST_MEMORY; 721bf215546Sopenharmony_ci goto fail_alloc; 722bf215546Sopenharmony_ci } 723bf215546Sopenharmony_ci } 724bf215546Sopenharmony_ci } 725bf215546Sopenharmony_ci pool->size = bo_size; 726bf215546Sopenharmony_ci pool->max_entry_count = pCreateInfo->maxSets; 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_ci list_inithead(&pool->desc_sets); 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci *pDescriptorPool = tu_descriptor_pool_to_handle(pool); 731bf215546Sopenharmony_ci return VK_SUCCESS; 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_cifail_map: 734bf215546Sopenharmony_ci tu_bo_finish(device, pool->bo); 735bf215546Sopenharmony_cifail_alloc: 736bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, pool); 737bf215546Sopenharmony_ci return ret; 738bf215546Sopenharmony_ci} 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 741bf215546Sopenharmony_citu_DestroyDescriptorPool(VkDevice _device, 742bf215546Sopenharmony_ci VkDescriptorPool _pool, 743bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 744bf215546Sopenharmony_ci{ 745bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 746bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_pool, pool, _pool); 747bf215546Sopenharmony_ci 748bf215546Sopenharmony_ci if (!pool) 749bf215546Sopenharmony_ci return; 750bf215546Sopenharmony_ci 751bf215546Sopenharmony_ci list_for_each_entry_safe(struct tu_descriptor_set, set, 752bf215546Sopenharmony_ci &pool->desc_sets, pool_link) { 753bf215546Sopenharmony_ci tu_descriptor_set_layout_unref(device, set->layout); 754bf215546Sopenharmony_ci } 755bf215546Sopenharmony_ci 756bf215546Sopenharmony_ci if (!pool->host_memory_base) { 757bf215546Sopenharmony_ci for(int i = 0; i < pool->entry_count; ++i) { 758bf215546Sopenharmony_ci tu_descriptor_set_destroy(device, pool, pool->entries[i].set, false); 759bf215546Sopenharmony_ci } 760bf215546Sopenharmony_ci } 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci if (pool->size) { 763bf215546Sopenharmony_ci if (pool->host_bo) 764bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, pAllocator, pool->host_bo); 765bf215546Sopenharmony_ci else 766bf215546Sopenharmony_ci tu_bo_finish(device, pool->bo); 767bf215546Sopenharmony_ci } 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, pool); 770bf215546Sopenharmony_ci} 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 773bf215546Sopenharmony_citu_ResetDescriptorPool(VkDevice _device, 774bf215546Sopenharmony_ci VkDescriptorPool descriptorPool, 775bf215546Sopenharmony_ci VkDescriptorPoolResetFlags flags) 776bf215546Sopenharmony_ci{ 777bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 778bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_pool, pool, descriptorPool); 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci list_for_each_entry_safe(struct tu_descriptor_set, set, 781bf215546Sopenharmony_ci &pool->desc_sets, pool_link) { 782bf215546Sopenharmony_ci tu_descriptor_set_layout_unref(device, set->layout); 783bf215546Sopenharmony_ci } 784bf215546Sopenharmony_ci list_inithead(&pool->desc_sets); 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci if (!pool->host_memory_base) { 787bf215546Sopenharmony_ci for(int i = 0; i < pool->entry_count; ++i) { 788bf215546Sopenharmony_ci tu_descriptor_set_destroy(device, pool, pool->entries[i].set, false); 789bf215546Sopenharmony_ci } 790bf215546Sopenharmony_ci pool->entry_count = 0; 791bf215546Sopenharmony_ci } 792bf215546Sopenharmony_ci 793bf215546Sopenharmony_ci pool->current_offset = 0; 794bf215546Sopenharmony_ci pool->host_memory_ptr = pool->host_memory_base; 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_ci return VK_SUCCESS; 797bf215546Sopenharmony_ci} 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 800bf215546Sopenharmony_citu_AllocateDescriptorSets(VkDevice _device, 801bf215546Sopenharmony_ci const VkDescriptorSetAllocateInfo *pAllocateInfo, 802bf215546Sopenharmony_ci VkDescriptorSet *pDescriptorSets) 803bf215546Sopenharmony_ci{ 804bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 805bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_pool, pool, pAllocateInfo->descriptorPool); 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 808bf215546Sopenharmony_ci uint32_t i; 809bf215546Sopenharmony_ci struct tu_descriptor_set *set = NULL; 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci const VkDescriptorSetVariableDescriptorCountAllocateInfo *variable_counts = 812bf215546Sopenharmony_ci vk_find_struct_const(pAllocateInfo->pNext, DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO); 813bf215546Sopenharmony_ci const uint32_t zero = 0; 814bf215546Sopenharmony_ci 815bf215546Sopenharmony_ci /* allocate a set of buffers for each shader to contain descriptors */ 816bf215546Sopenharmony_ci for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 817bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set_layout, layout, 818bf215546Sopenharmony_ci pAllocateInfo->pSetLayouts[i]); 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci const uint32_t *variable_count = NULL; 821bf215546Sopenharmony_ci if (variable_counts) { 822bf215546Sopenharmony_ci if (i < variable_counts->descriptorSetCount) 823bf215546Sopenharmony_ci variable_count = variable_counts->pDescriptorCounts + i; 824bf215546Sopenharmony_ci else 825bf215546Sopenharmony_ci variable_count = &zero; 826bf215546Sopenharmony_ci } 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci assert(!(layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)); 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ci result = tu_descriptor_set_create(device, pool, layout, variable_count, &set); 831bf215546Sopenharmony_ci if (result != VK_SUCCESS) 832bf215546Sopenharmony_ci break; 833bf215546Sopenharmony_ci 834bf215546Sopenharmony_ci pDescriptorSets[i] = tu_descriptor_set_to_handle(set); 835bf215546Sopenharmony_ci } 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 838bf215546Sopenharmony_ci tu_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool, 839bf215546Sopenharmony_ci i, pDescriptorSets); 840bf215546Sopenharmony_ci for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 841bf215546Sopenharmony_ci pDescriptorSets[i] = VK_NULL_HANDLE; 842bf215546Sopenharmony_ci } 843bf215546Sopenharmony_ci } 844bf215546Sopenharmony_ci return result; 845bf215546Sopenharmony_ci} 846bf215546Sopenharmony_ci 847bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 848bf215546Sopenharmony_citu_FreeDescriptorSets(VkDevice _device, 849bf215546Sopenharmony_ci VkDescriptorPool descriptorPool, 850bf215546Sopenharmony_ci uint32_t count, 851bf215546Sopenharmony_ci const VkDescriptorSet *pDescriptorSets) 852bf215546Sopenharmony_ci{ 853bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 854bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_pool, pool, descriptorPool); 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci for (uint32_t i = 0; i < count; i++) { 857bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set, set, pDescriptorSets[i]); 858bf215546Sopenharmony_ci 859bf215546Sopenharmony_ci if (set) { 860bf215546Sopenharmony_ci tu_descriptor_set_layout_unref(device, set->layout); 861bf215546Sopenharmony_ci list_del(&set->pool_link); 862bf215546Sopenharmony_ci } 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_ci if (set && !pool->host_memory_base) 865bf215546Sopenharmony_ci tu_descriptor_set_destroy(device, pool, set, true); 866bf215546Sopenharmony_ci } 867bf215546Sopenharmony_ci return VK_SUCCESS; 868bf215546Sopenharmony_ci} 869bf215546Sopenharmony_ci 870bf215546Sopenharmony_cistatic void 871bf215546Sopenharmony_ciwrite_texel_buffer_descriptor(uint32_t *dst, const VkBufferView buffer_view) 872bf215546Sopenharmony_ci{ 873bf215546Sopenharmony_ci if (buffer_view == VK_NULL_HANDLE) { 874bf215546Sopenharmony_ci memset(dst, 0, A6XX_TEX_CONST_DWORDS * sizeof(uint32_t)); 875bf215546Sopenharmony_ci } else { 876bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_buffer_view, view, buffer_view); 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci memcpy(dst, view->descriptor, sizeof(view->descriptor)); 879bf215546Sopenharmony_ci } 880bf215546Sopenharmony_ci} 881bf215546Sopenharmony_ci 882bf215546Sopenharmony_cistatic uint32_t get_range(struct tu_buffer *buf, VkDeviceSize offset, 883bf215546Sopenharmony_ci VkDeviceSize range) 884bf215546Sopenharmony_ci{ 885bf215546Sopenharmony_ci if (range == VK_WHOLE_SIZE) { 886bf215546Sopenharmony_ci return buf->size - offset; 887bf215546Sopenharmony_ci } else { 888bf215546Sopenharmony_ci return range; 889bf215546Sopenharmony_ci } 890bf215546Sopenharmony_ci} 891bf215546Sopenharmony_ci 892bf215546Sopenharmony_cistatic void 893bf215546Sopenharmony_ciwrite_buffer_descriptor(const struct tu_device *device, 894bf215546Sopenharmony_ci uint32_t *dst, 895bf215546Sopenharmony_ci const VkDescriptorBufferInfo *buffer_info) 896bf215546Sopenharmony_ci{ 897bf215546Sopenharmony_ci bool storage_16bit = device->physical_device->info->a6xx.storage_16bit; 898bf215546Sopenharmony_ci /* newer a6xx allows using 16-bit descriptor for both 16-bit and 32-bit 899bf215546Sopenharmony_ci * access, but we need to keep a 32-bit descriptor for readonly access via 900bf215546Sopenharmony_ci * isam. 901bf215546Sopenharmony_ci */ 902bf215546Sopenharmony_ci unsigned descriptors = storage_16bit ? 2 : 1; 903bf215546Sopenharmony_ci if (buffer_info->buffer == VK_NULL_HANDLE) { 904bf215546Sopenharmony_ci memset(dst, 0, descriptors * A6XX_TEX_CONST_DWORDS * sizeof(uint32_t)); 905bf215546Sopenharmony_ci return; 906bf215546Sopenharmony_ci } 907bf215546Sopenharmony_ci 908bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_buffer, buffer, buffer_info->buffer); 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci assert((buffer_info->offset & 63) == 0); /* minStorageBufferOffsetAlignment */ 911bf215546Sopenharmony_ci uint64_t va = buffer->iova + buffer_info->offset; 912bf215546Sopenharmony_ci uint32_t range = get_range(buffer, buffer_info->offset, buffer_info->range); 913bf215546Sopenharmony_ci 914bf215546Sopenharmony_ci for (unsigned i = 0; i < descriptors; i++) { 915bf215546Sopenharmony_ci if (storage_16bit && i == 0) { 916bf215546Sopenharmony_ci dst[0] = A6XX_TEX_CONST_0_TILE_MODE(TILE6_LINEAR) | A6XX_TEX_CONST_0_FMT(FMT6_16_UINT); 917bf215546Sopenharmony_ci dst[1] = DIV_ROUND_UP(range, 2); 918bf215546Sopenharmony_ci } else { 919bf215546Sopenharmony_ci dst[0] = A6XX_TEX_CONST_0_TILE_MODE(TILE6_LINEAR) | A6XX_TEX_CONST_0_FMT(FMT6_32_UINT); 920bf215546Sopenharmony_ci dst[1] = DIV_ROUND_UP(range, 4); 921bf215546Sopenharmony_ci } 922bf215546Sopenharmony_ci dst[2] = 923bf215546Sopenharmony_ci A6XX_TEX_CONST_2_BUFFER | A6XX_TEX_CONST_2_TYPE(A6XX_TEX_BUFFER); 924bf215546Sopenharmony_ci dst[3] = 0; 925bf215546Sopenharmony_ci dst[4] = A6XX_TEX_CONST_4_BASE_LO(va); 926bf215546Sopenharmony_ci dst[5] = A6XX_TEX_CONST_5_BASE_HI(va >> 32); 927bf215546Sopenharmony_ci for (int j = 6; j < A6XX_TEX_CONST_DWORDS; j++) 928bf215546Sopenharmony_ci dst[j] = 0; 929bf215546Sopenharmony_ci dst += A6XX_TEX_CONST_DWORDS; 930bf215546Sopenharmony_ci } 931bf215546Sopenharmony_ci} 932bf215546Sopenharmony_ci 933bf215546Sopenharmony_cistatic void 934bf215546Sopenharmony_ciwrite_ubo_descriptor(uint32_t *dst, const VkDescriptorBufferInfo *buffer_info) 935bf215546Sopenharmony_ci{ 936bf215546Sopenharmony_ci if (buffer_info->buffer == VK_NULL_HANDLE) { 937bf215546Sopenharmony_ci dst[0] = dst[1] = 0; 938bf215546Sopenharmony_ci return; 939bf215546Sopenharmony_ci } 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_buffer, buffer, buffer_info->buffer); 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_ci uint32_t range = get_range(buffer, buffer_info->offset, buffer_info->range); 944bf215546Sopenharmony_ci /* The HW range is in vec4 units */ 945bf215546Sopenharmony_ci range = ALIGN_POT(range, 16) / 16; 946bf215546Sopenharmony_ci uint64_t va = buffer->iova + buffer_info->offset; 947bf215546Sopenharmony_ci 948bf215546Sopenharmony_ci dst[0] = A6XX_UBO_0_BASE_LO(va); 949bf215546Sopenharmony_ci dst[1] = A6XX_UBO_1_BASE_HI(va >> 32) | A6XX_UBO_1_SIZE(range); 950bf215546Sopenharmony_ci} 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_cistatic void 953bf215546Sopenharmony_ciwrite_image_descriptor(uint32_t *dst, 954bf215546Sopenharmony_ci VkDescriptorType descriptor_type, 955bf215546Sopenharmony_ci const VkDescriptorImageInfo *image_info) 956bf215546Sopenharmony_ci{ 957bf215546Sopenharmony_ci if (image_info->imageView == VK_NULL_HANDLE) { 958bf215546Sopenharmony_ci memset(dst, 0, A6XX_TEX_CONST_DWORDS * sizeof(uint32_t)); 959bf215546Sopenharmony_ci return; 960bf215546Sopenharmony_ci } 961bf215546Sopenharmony_ci 962bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_image_view, iview, image_info->imageView); 963bf215546Sopenharmony_ci 964bf215546Sopenharmony_ci if (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) { 965bf215546Sopenharmony_ci memcpy(dst, iview->view.storage_descriptor, sizeof(iview->view.storage_descriptor)); 966bf215546Sopenharmony_ci } else { 967bf215546Sopenharmony_ci memcpy(dst, iview->view.descriptor, sizeof(iview->view.descriptor)); 968bf215546Sopenharmony_ci } 969bf215546Sopenharmony_ci} 970bf215546Sopenharmony_ci 971bf215546Sopenharmony_cistatic void 972bf215546Sopenharmony_ciwrite_combined_image_sampler_descriptor(uint32_t *dst, 973bf215546Sopenharmony_ci VkDescriptorType descriptor_type, 974bf215546Sopenharmony_ci const VkDescriptorImageInfo *image_info, 975bf215546Sopenharmony_ci bool has_sampler) 976bf215546Sopenharmony_ci{ 977bf215546Sopenharmony_ci write_image_descriptor(dst, descriptor_type, image_info); 978bf215546Sopenharmony_ci /* copy over sampler state */ 979bf215546Sopenharmony_ci if (has_sampler) { 980bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_sampler, sampler, image_info->sampler); 981bf215546Sopenharmony_ci memcpy(dst + A6XX_TEX_CONST_DWORDS, sampler->descriptor, sizeof(sampler->descriptor)); 982bf215546Sopenharmony_ci } 983bf215546Sopenharmony_ci} 984bf215546Sopenharmony_ci 985bf215546Sopenharmony_cistatic void 986bf215546Sopenharmony_ciwrite_sampler_descriptor(uint32_t *dst, const VkDescriptorImageInfo *image_info) 987bf215546Sopenharmony_ci{ 988bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_sampler, sampler, image_info->sampler); 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci memcpy(dst, sampler->descriptor, sizeof(sampler->descriptor)); 991bf215546Sopenharmony_ci} 992bf215546Sopenharmony_ci 993bf215546Sopenharmony_ci/* note: this is used with immutable samplers in push descriptors */ 994bf215546Sopenharmony_cistatic void 995bf215546Sopenharmony_ciwrite_sampler_push(uint32_t *dst, const struct tu_sampler *sampler) 996bf215546Sopenharmony_ci{ 997bf215546Sopenharmony_ci memcpy(dst, sampler->descriptor, sizeof(sampler->descriptor)); 998bf215546Sopenharmony_ci} 999bf215546Sopenharmony_ci 1000bf215546Sopenharmony_civoid 1001bf215546Sopenharmony_citu_update_descriptor_sets(const struct tu_device *device, 1002bf215546Sopenharmony_ci VkDescriptorSet dstSetOverride, 1003bf215546Sopenharmony_ci uint32_t descriptorWriteCount, 1004bf215546Sopenharmony_ci const VkWriteDescriptorSet *pDescriptorWrites, 1005bf215546Sopenharmony_ci uint32_t descriptorCopyCount, 1006bf215546Sopenharmony_ci const VkCopyDescriptorSet *pDescriptorCopies) 1007bf215546Sopenharmony_ci{ 1008bf215546Sopenharmony_ci uint32_t i, j; 1009bf215546Sopenharmony_ci for (i = 0; i < descriptorWriteCount; i++) { 1010bf215546Sopenharmony_ci const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i]; 1011bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set, set, dstSetOverride ?: writeset->dstSet); 1012bf215546Sopenharmony_ci const struct tu_descriptor_set_binding_layout *binding_layout = 1013bf215546Sopenharmony_ci set->layout->binding + writeset->dstBinding; 1014bf215546Sopenharmony_ci uint32_t *ptr = set->mapped_ptr; 1015bf215546Sopenharmony_ci if (writeset->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || 1016bf215546Sopenharmony_ci writeset->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 1017bf215546Sopenharmony_ci ptr = set->dynamic_descriptors; 1018bf215546Sopenharmony_ci ptr += binding_layout->dynamic_offset_offset / 4; 1019bf215546Sopenharmony_ci } else { 1020bf215546Sopenharmony_ci ptr = set->mapped_ptr; 1021bf215546Sopenharmony_ci ptr += binding_layout->offset / 4; 1022bf215546Sopenharmony_ci } 1023bf215546Sopenharmony_ci 1024bf215546Sopenharmony_ci /* for immutable samplers with push descriptors: */ 1025bf215546Sopenharmony_ci const bool copy_immutable_samplers = 1026bf215546Sopenharmony_ci dstSetOverride && binding_layout->immutable_samplers_offset; 1027bf215546Sopenharmony_ci const struct tu_sampler *samplers = 1028bf215546Sopenharmony_ci tu_immutable_samplers(set->layout, binding_layout); 1029bf215546Sopenharmony_ci 1030bf215546Sopenharmony_ci ptr += (binding_layout->size / 4) * writeset->dstArrayElement; 1031bf215546Sopenharmony_ci for (j = 0; j < writeset->descriptorCount; ++j) { 1032bf215546Sopenharmony_ci switch(writeset->descriptorType) { 1033bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 1034bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 1035bf215546Sopenharmony_ci write_ubo_descriptor(ptr, writeset->pBufferInfo + j); 1036bf215546Sopenharmony_ci break; 1037bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 1038bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 1039bf215546Sopenharmony_ci write_buffer_descriptor(device, ptr, writeset->pBufferInfo + j); 1040bf215546Sopenharmony_ci break; 1041bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 1042bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 1043bf215546Sopenharmony_ci write_texel_buffer_descriptor(ptr, writeset->pTexelBufferView[j]); 1044bf215546Sopenharmony_ci break; 1045bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 1046bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 1047bf215546Sopenharmony_ci write_image_descriptor(ptr, writeset->descriptorType, writeset->pImageInfo + j); 1048bf215546Sopenharmony_ci break; 1049bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 1050bf215546Sopenharmony_ci write_combined_image_sampler_descriptor(ptr, 1051bf215546Sopenharmony_ci writeset->descriptorType, 1052bf215546Sopenharmony_ci writeset->pImageInfo + j, 1053bf215546Sopenharmony_ci !binding_layout->immutable_samplers_offset); 1054bf215546Sopenharmony_ci 1055bf215546Sopenharmony_ci if (copy_immutable_samplers) 1056bf215546Sopenharmony_ci write_sampler_push(ptr + A6XX_TEX_CONST_DWORDS, &samplers[writeset->dstArrayElement + j]); 1057bf215546Sopenharmony_ci break; 1058bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLER: 1059bf215546Sopenharmony_ci if (!binding_layout->immutable_samplers_offset) 1060bf215546Sopenharmony_ci write_sampler_descriptor(ptr, writeset->pImageInfo + j); 1061bf215546Sopenharmony_ci else if (copy_immutable_samplers) 1062bf215546Sopenharmony_ci write_sampler_push(ptr, &samplers[writeset->dstArrayElement + j]); 1063bf215546Sopenharmony_ci break; 1064bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 1065bf215546Sopenharmony_ci /* nothing in descriptor set - framebuffer state is used instead */ 1066bf215546Sopenharmony_ci if (unlikely(device->instance->debug_flags & TU_DEBUG_DYNAMIC)) 1067bf215546Sopenharmony_ci write_image_descriptor(ptr, writeset->descriptorType, writeset->pImageInfo + j); 1068bf215546Sopenharmony_ci break; 1069bf215546Sopenharmony_ci default: 1070bf215546Sopenharmony_ci unreachable("unimplemented descriptor type"); 1071bf215546Sopenharmony_ci break; 1072bf215546Sopenharmony_ci } 1073bf215546Sopenharmony_ci ptr += binding_layout->size / 4; 1074bf215546Sopenharmony_ci } 1075bf215546Sopenharmony_ci } 1076bf215546Sopenharmony_ci 1077bf215546Sopenharmony_ci for (i = 0; i < descriptorCopyCount; i++) { 1078bf215546Sopenharmony_ci const VkCopyDescriptorSet *copyset = &pDescriptorCopies[i]; 1079bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set, src_set, 1080bf215546Sopenharmony_ci copyset->srcSet); 1081bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set, dst_set, 1082bf215546Sopenharmony_ci copyset->dstSet); 1083bf215546Sopenharmony_ci const struct tu_descriptor_set_binding_layout *src_binding_layout = 1084bf215546Sopenharmony_ci src_set->layout->binding + copyset->srcBinding; 1085bf215546Sopenharmony_ci const struct tu_descriptor_set_binding_layout *dst_binding_layout = 1086bf215546Sopenharmony_ci dst_set->layout->binding + copyset->dstBinding; 1087bf215546Sopenharmony_ci uint32_t *src_ptr = src_set->mapped_ptr; 1088bf215546Sopenharmony_ci uint32_t *dst_ptr = dst_set->mapped_ptr; 1089bf215546Sopenharmony_ci if (src_binding_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || 1090bf215546Sopenharmony_ci src_binding_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 1091bf215546Sopenharmony_ci src_ptr = src_set->dynamic_descriptors; 1092bf215546Sopenharmony_ci dst_ptr = dst_set->dynamic_descriptors; 1093bf215546Sopenharmony_ci src_ptr += src_binding_layout->dynamic_offset_offset / 4; 1094bf215546Sopenharmony_ci dst_ptr += dst_binding_layout->dynamic_offset_offset / 4; 1095bf215546Sopenharmony_ci } else { 1096bf215546Sopenharmony_ci src_ptr = src_set->mapped_ptr; 1097bf215546Sopenharmony_ci dst_ptr = dst_set->mapped_ptr; 1098bf215546Sopenharmony_ci src_ptr += src_binding_layout->offset / 4; 1099bf215546Sopenharmony_ci dst_ptr += dst_binding_layout->offset / 4; 1100bf215546Sopenharmony_ci } 1101bf215546Sopenharmony_ci 1102bf215546Sopenharmony_ci src_ptr += src_binding_layout->size * copyset->srcArrayElement / 4; 1103bf215546Sopenharmony_ci dst_ptr += dst_binding_layout->size * copyset->dstArrayElement / 4; 1104bf215546Sopenharmony_ci 1105bf215546Sopenharmony_ci /* In case of copies between mutable descriptor types 1106bf215546Sopenharmony_ci * and non-mutable descriptor types. 1107bf215546Sopenharmony_ci */ 1108bf215546Sopenharmony_ci uint32_t copy_size = MIN2(src_binding_layout->size, dst_binding_layout->size); 1109bf215546Sopenharmony_ci 1110bf215546Sopenharmony_ci for (j = 0; j < copyset->descriptorCount; ++j) { 1111bf215546Sopenharmony_ci memcpy(dst_ptr, src_ptr, copy_size); 1112bf215546Sopenharmony_ci 1113bf215546Sopenharmony_ci src_ptr += src_binding_layout->size / 4; 1114bf215546Sopenharmony_ci dst_ptr += dst_binding_layout->size / 4; 1115bf215546Sopenharmony_ci } 1116bf215546Sopenharmony_ci } 1117bf215546Sopenharmony_ci} 1118bf215546Sopenharmony_ci 1119bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1120bf215546Sopenharmony_citu_UpdateDescriptorSets(VkDevice _device, 1121bf215546Sopenharmony_ci uint32_t descriptorWriteCount, 1122bf215546Sopenharmony_ci const VkWriteDescriptorSet *pDescriptorWrites, 1123bf215546Sopenharmony_ci uint32_t descriptorCopyCount, 1124bf215546Sopenharmony_ci const VkCopyDescriptorSet *pDescriptorCopies) 1125bf215546Sopenharmony_ci{ 1126bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 1127bf215546Sopenharmony_ci tu_update_descriptor_sets(device, VK_NULL_HANDLE, 1128bf215546Sopenharmony_ci descriptorWriteCount, pDescriptorWrites, 1129bf215546Sopenharmony_ci descriptorCopyCount, pDescriptorCopies); 1130bf215546Sopenharmony_ci} 1131bf215546Sopenharmony_ci 1132bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1133bf215546Sopenharmony_citu_CreateDescriptorUpdateTemplate( 1134bf215546Sopenharmony_ci VkDevice _device, 1135bf215546Sopenharmony_ci const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo, 1136bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1137bf215546Sopenharmony_ci VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate) 1138bf215546Sopenharmony_ci{ 1139bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 1140bf215546Sopenharmony_ci struct tu_descriptor_set_layout *set_layout = NULL; 1141bf215546Sopenharmony_ci const uint32_t entry_count = pCreateInfo->descriptorUpdateEntryCount; 1142bf215546Sopenharmony_ci const size_t size = 1143bf215546Sopenharmony_ci sizeof(struct tu_descriptor_update_template) + 1144bf215546Sopenharmony_ci sizeof(struct tu_descriptor_update_template_entry) * entry_count; 1145bf215546Sopenharmony_ci struct tu_descriptor_update_template *templ; 1146bf215546Sopenharmony_ci 1147bf215546Sopenharmony_ci templ = vk_object_alloc(&device->vk, pAllocator, size, 1148bf215546Sopenharmony_ci VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE); 1149bf215546Sopenharmony_ci if (!templ) 1150bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci templ->entry_count = entry_count; 1153bf215546Sopenharmony_ci 1154bf215546Sopenharmony_ci if (pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR) { 1155bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_pipeline_layout, pipeline_layout, pCreateInfo->pipelineLayout); 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_ci /* descriptorSetLayout should be ignored for push descriptors 1158bf215546Sopenharmony_ci * and instead it refers to pipelineLayout and set. 1159bf215546Sopenharmony_ci */ 1160bf215546Sopenharmony_ci assert(pCreateInfo->set < MAX_SETS); 1161bf215546Sopenharmony_ci set_layout = pipeline_layout->set[pCreateInfo->set].layout; 1162bf215546Sopenharmony_ci 1163bf215546Sopenharmony_ci templ->bind_point = pCreateInfo->pipelineBindPoint; 1164bf215546Sopenharmony_ci } else { 1165bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set_layout, _set_layout, 1166bf215546Sopenharmony_ci pCreateInfo->descriptorSetLayout); 1167bf215546Sopenharmony_ci set_layout = _set_layout; 1168bf215546Sopenharmony_ci } 1169bf215546Sopenharmony_ci 1170bf215546Sopenharmony_ci for (uint32_t i = 0; i < entry_count; i++) { 1171bf215546Sopenharmony_ci const VkDescriptorUpdateTemplateEntry *entry = &pCreateInfo->pDescriptorUpdateEntries[i]; 1172bf215546Sopenharmony_ci 1173bf215546Sopenharmony_ci const struct tu_descriptor_set_binding_layout *binding_layout = 1174bf215546Sopenharmony_ci set_layout->binding + entry->dstBinding; 1175bf215546Sopenharmony_ci uint32_t dst_offset, dst_stride; 1176bf215546Sopenharmony_ci const struct tu_sampler *immutable_samplers = NULL; 1177bf215546Sopenharmony_ci 1178bf215546Sopenharmony_ci /* dst_offset is an offset into dynamic_descriptors when the descriptor 1179bf215546Sopenharmony_ci * is dynamic, and an offset into mapped_ptr otherwise. 1180bf215546Sopenharmony_ci */ 1181bf215546Sopenharmony_ci switch (entry->descriptorType) { 1182bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 1183bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 1184bf215546Sopenharmony_ci dst_offset = binding_layout->dynamic_offset_offset / 4; 1185bf215546Sopenharmony_ci break; 1186bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 1187bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLER: 1188bf215546Sopenharmony_ci if (pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR && 1189bf215546Sopenharmony_ci binding_layout->immutable_samplers_offset) { 1190bf215546Sopenharmony_ci immutable_samplers = 1191bf215546Sopenharmony_ci tu_immutable_samplers(set_layout, binding_layout) + entry->dstArrayElement; 1192bf215546Sopenharmony_ci } 1193bf215546Sopenharmony_ci FALLTHROUGH; 1194bf215546Sopenharmony_ci default: 1195bf215546Sopenharmony_ci dst_offset = binding_layout->offset / 4; 1196bf215546Sopenharmony_ci } 1197bf215546Sopenharmony_ci 1198bf215546Sopenharmony_ci dst_offset += (binding_layout->size * entry->dstArrayElement) / 4; 1199bf215546Sopenharmony_ci dst_stride = binding_layout->size / 4; 1200bf215546Sopenharmony_ci 1201bf215546Sopenharmony_ci templ->entry[i] = (struct tu_descriptor_update_template_entry) { 1202bf215546Sopenharmony_ci .descriptor_type = entry->descriptorType, 1203bf215546Sopenharmony_ci .descriptor_count = entry->descriptorCount, 1204bf215546Sopenharmony_ci .src_offset = entry->offset, 1205bf215546Sopenharmony_ci .src_stride = entry->stride, 1206bf215546Sopenharmony_ci .dst_offset = dst_offset, 1207bf215546Sopenharmony_ci .dst_stride = dst_stride, 1208bf215546Sopenharmony_ci .has_sampler = !binding_layout->immutable_samplers_offset, 1209bf215546Sopenharmony_ci .immutable_samplers = immutable_samplers, 1210bf215546Sopenharmony_ci }; 1211bf215546Sopenharmony_ci } 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci *pDescriptorUpdateTemplate = 1214bf215546Sopenharmony_ci tu_descriptor_update_template_to_handle(templ); 1215bf215546Sopenharmony_ci 1216bf215546Sopenharmony_ci return VK_SUCCESS; 1217bf215546Sopenharmony_ci} 1218bf215546Sopenharmony_ci 1219bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1220bf215546Sopenharmony_citu_DestroyDescriptorUpdateTemplate( 1221bf215546Sopenharmony_ci VkDevice _device, 1222bf215546Sopenharmony_ci VkDescriptorUpdateTemplate descriptorUpdateTemplate, 1223bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 1224bf215546Sopenharmony_ci{ 1225bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 1226bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_update_template, templ, 1227bf215546Sopenharmony_ci descriptorUpdateTemplate); 1228bf215546Sopenharmony_ci 1229bf215546Sopenharmony_ci if (!templ) 1230bf215546Sopenharmony_ci return; 1231bf215546Sopenharmony_ci 1232bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, templ); 1233bf215546Sopenharmony_ci} 1234bf215546Sopenharmony_ci 1235bf215546Sopenharmony_civoid 1236bf215546Sopenharmony_citu_update_descriptor_set_with_template( 1237bf215546Sopenharmony_ci const struct tu_device *device, 1238bf215546Sopenharmony_ci struct tu_descriptor_set *set, 1239bf215546Sopenharmony_ci VkDescriptorUpdateTemplate descriptorUpdateTemplate, 1240bf215546Sopenharmony_ci const void *pData) 1241bf215546Sopenharmony_ci{ 1242bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_update_template, templ, 1243bf215546Sopenharmony_ci descriptorUpdateTemplate); 1244bf215546Sopenharmony_ci 1245bf215546Sopenharmony_ci for (uint32_t i = 0; i < templ->entry_count; i++) { 1246bf215546Sopenharmony_ci uint32_t *ptr = set->mapped_ptr; 1247bf215546Sopenharmony_ci const void *src = ((const char *) pData) + templ->entry[i].src_offset; 1248bf215546Sopenharmony_ci const struct tu_sampler *samplers = templ->entry[i].immutable_samplers; 1249bf215546Sopenharmony_ci 1250bf215546Sopenharmony_ci ptr += templ->entry[i].dst_offset; 1251bf215546Sopenharmony_ci unsigned dst_offset = templ->entry[i].dst_offset; 1252bf215546Sopenharmony_ci for (unsigned j = 0; j < templ->entry[i].descriptor_count; ++j) { 1253bf215546Sopenharmony_ci switch(templ->entry[i].descriptor_type) { 1254bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: { 1255bf215546Sopenharmony_ci assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)); 1256bf215546Sopenharmony_ci write_ubo_descriptor(set->dynamic_descriptors + dst_offset, src); 1257bf215546Sopenharmony_ci break; 1258bf215546Sopenharmony_ci } 1259bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 1260bf215546Sopenharmony_ci write_ubo_descriptor(ptr, src); 1261bf215546Sopenharmony_ci break; 1262bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: { 1263bf215546Sopenharmony_ci assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)); 1264bf215546Sopenharmony_ci write_buffer_descriptor(device, set->dynamic_descriptors + dst_offset, src); 1265bf215546Sopenharmony_ci break; 1266bf215546Sopenharmony_ci } 1267bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 1268bf215546Sopenharmony_ci write_buffer_descriptor(device, ptr, src); 1269bf215546Sopenharmony_ci break; 1270bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 1271bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 1272bf215546Sopenharmony_ci write_texel_buffer_descriptor(ptr, *(VkBufferView *) src); 1273bf215546Sopenharmony_ci break; 1274bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 1275bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { 1276bf215546Sopenharmony_ci write_image_descriptor(ptr, templ->entry[i].descriptor_type, src); 1277bf215546Sopenharmony_ci break; 1278bf215546Sopenharmony_ci } 1279bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 1280bf215546Sopenharmony_ci write_combined_image_sampler_descriptor(ptr, 1281bf215546Sopenharmony_ci templ->entry[i].descriptor_type, 1282bf215546Sopenharmony_ci src, 1283bf215546Sopenharmony_ci templ->entry[i].has_sampler); 1284bf215546Sopenharmony_ci if (samplers) 1285bf215546Sopenharmony_ci write_sampler_push(ptr + A6XX_TEX_CONST_DWORDS, &samplers[j]); 1286bf215546Sopenharmony_ci break; 1287bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLER: 1288bf215546Sopenharmony_ci if (templ->entry[i].has_sampler) 1289bf215546Sopenharmony_ci write_sampler_descriptor(ptr, src); 1290bf215546Sopenharmony_ci else if (samplers) 1291bf215546Sopenharmony_ci write_sampler_push(ptr, &samplers[j]); 1292bf215546Sopenharmony_ci break; 1293bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 1294bf215546Sopenharmony_ci /* nothing in descriptor set - framebuffer state is used instead */ 1295bf215546Sopenharmony_ci if (unlikely(device->instance->debug_flags & TU_DEBUG_DYNAMIC)) 1296bf215546Sopenharmony_ci write_image_descriptor(ptr, templ->entry[i].descriptor_type, src); 1297bf215546Sopenharmony_ci break; 1298bf215546Sopenharmony_ci default: 1299bf215546Sopenharmony_ci unreachable("unimplemented descriptor type"); 1300bf215546Sopenharmony_ci break; 1301bf215546Sopenharmony_ci } 1302bf215546Sopenharmony_ci src = (char *) src + templ->entry[i].src_stride; 1303bf215546Sopenharmony_ci ptr += templ->entry[i].dst_stride; 1304bf215546Sopenharmony_ci dst_offset += templ->entry[i].dst_stride; 1305bf215546Sopenharmony_ci } 1306bf215546Sopenharmony_ci } 1307bf215546Sopenharmony_ci} 1308bf215546Sopenharmony_ci 1309bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1310bf215546Sopenharmony_citu_UpdateDescriptorSetWithTemplate( 1311bf215546Sopenharmony_ci VkDevice _device, 1312bf215546Sopenharmony_ci VkDescriptorSet descriptorSet, 1313bf215546Sopenharmony_ci VkDescriptorUpdateTemplate descriptorUpdateTemplate, 1314bf215546Sopenharmony_ci const void *pData) 1315bf215546Sopenharmony_ci{ 1316bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 1317bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_descriptor_set, set, descriptorSet); 1318bf215546Sopenharmony_ci 1319bf215546Sopenharmony_ci tu_update_descriptor_set_with_template(device, set, descriptorUpdateTemplate, pData); 1320bf215546Sopenharmony_ci} 1321bf215546Sopenharmony_ci 1322bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1323bf215546Sopenharmony_citu_CreateSamplerYcbcrConversion( 1324bf215546Sopenharmony_ci VkDevice _device, 1325bf215546Sopenharmony_ci const VkSamplerYcbcrConversionCreateInfo *pCreateInfo, 1326bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1327bf215546Sopenharmony_ci VkSamplerYcbcrConversion *pYcbcrConversion) 1328bf215546Sopenharmony_ci{ 1329bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 1330bf215546Sopenharmony_ci struct tu_sampler_ycbcr_conversion *conversion; 1331bf215546Sopenharmony_ci 1332bf215546Sopenharmony_ci conversion = vk_object_alloc(&device->vk, pAllocator, sizeof(*conversion), 1333bf215546Sopenharmony_ci VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION); 1334bf215546Sopenharmony_ci if (!conversion) 1335bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1336bf215546Sopenharmony_ci 1337bf215546Sopenharmony_ci conversion->format = pCreateInfo->format; 1338bf215546Sopenharmony_ci conversion->ycbcr_model = pCreateInfo->ycbcrModel; 1339bf215546Sopenharmony_ci conversion->ycbcr_range = pCreateInfo->ycbcrRange; 1340bf215546Sopenharmony_ci conversion->components = pCreateInfo->components; 1341bf215546Sopenharmony_ci conversion->chroma_offsets[0] = pCreateInfo->xChromaOffset; 1342bf215546Sopenharmony_ci conversion->chroma_offsets[1] = pCreateInfo->yChromaOffset; 1343bf215546Sopenharmony_ci conversion->chroma_filter = pCreateInfo->chromaFilter; 1344bf215546Sopenharmony_ci 1345bf215546Sopenharmony_ci *pYcbcrConversion = tu_sampler_ycbcr_conversion_to_handle(conversion); 1346bf215546Sopenharmony_ci return VK_SUCCESS; 1347bf215546Sopenharmony_ci} 1348bf215546Sopenharmony_ci 1349bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1350bf215546Sopenharmony_citu_DestroySamplerYcbcrConversion(VkDevice _device, 1351bf215546Sopenharmony_ci VkSamplerYcbcrConversion ycbcrConversion, 1352bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 1353bf215546Sopenharmony_ci{ 1354bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_device, device, _device); 1355bf215546Sopenharmony_ci TU_FROM_HANDLE(tu_sampler_ycbcr_conversion, ycbcr_conversion, ycbcrConversion); 1356bf215546Sopenharmony_ci 1357bf215546Sopenharmony_ci if (!ycbcr_conversion) 1358bf215546Sopenharmony_ci return; 1359bf215546Sopenharmony_ci 1360bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, ycbcr_conversion); 1361bf215546Sopenharmony_ci} 1362