~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/microsoft/vulkan/dzn_descriptor_set.c

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
860
860
   if (device->bindless)
861
861
      root_flags |= D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED |
862
862
                    D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED;
863
 
#if D3D12_SDK_VERSION >= 609
864
863
   if (pdev->root_sig_version >= D3D_ROOT_SIGNATURE_VERSION_1_2) {
865
864
      root_sig_desc.Desc_1_2 = (D3D12_ROOT_SIGNATURE_DESC2){
866
865
         .NumParameters = layout->root.param_count,
869
868
         .pStaticSamplers = static_sampler_descs,
870
869
         .Flags = root_flags,
871
870
      };
872
 
   } else
873
 
#endif
874
 
   {
 
871
   } else {
875
872
      root_sig_desc.Desc_1_1 = (D3D12_ROOT_SIGNATURE_DESC1){
876
873
            .NumParameters = layout->root.param_count,
877
874
            .pParameters = layout->root.param_count ? root_params : NULL,
1089
1086
}
1090
1087
 
1091
1088
static void
1092
 
dzn_bindless_descriptor_set_write_sampler_desc(struct dxil_spirv_bindless_entry *map,
 
1089
dzn_bindless_descriptor_set_write_sampler_desc(volatile struct dxil_spirv_bindless_entry *map,
1093
1090
                                               uint32_t desc_offset,
1094
1091
                                               const struct dzn_sampler *sampler)
1095
1092
{
1097
1094
}
1098
1095
 
1099
1096
static void
1100
 
dzn_bindless_descriptor_set_write_image_view_desc(struct dxil_spirv_bindless_entry *map,
 
1097
dzn_bindless_descriptor_set_write_image_view_desc(volatile struct dxil_spirv_bindless_entry *map,
1101
1098
                                                  VkDescriptorType type,
1102
1099
                                                  uint32_t desc_offset,
1103
1100
                                                  const struct dzn_image_view *iview)
1117
1114
}
1118
1115
 
1119
1116
static void
1120
 
dzn_bindless_descriptor_set_write_buffer_view_desc(struct dxil_spirv_bindless_entry *map,
 
1117
dzn_bindless_descriptor_set_write_buffer_view_desc(volatile struct dxil_spirv_bindless_entry *map,
1121
1118
                                                   VkDescriptorType type,
1122
1119
                                                   uint32_t desc_offset,
1123
1120
                                                   const struct dzn_buffer_view *bview)
1134
1131
   }
1135
1132
}
1136
1133
 
1137
 
static bool
1138
 
need_custom_buffer_descriptor(struct dzn_device *device, const struct dzn_buffer_desc *info)
1139
 
{
1140
 
   if (info->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
1141
 
       info->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
1142
 
      uint64_t upper_bound = info->range == VK_WHOLE_SIZE ? info->buffer->size :
1143
 
         info->offset + info->range;
1144
 
      /* The buffer's default CBV only addresses the first 64KiB. If this view needs a higher
1145
 
       * upper bound, then we need a custom descriptor. */
1146
 
      if (upper_bound > D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 4 * sizeof(float)) {
1147
 
         /* It's invalid to use WHOLE_SIZE if it would address more than 64KiB, so if they're
1148
 
          * using it on a buffer that large, it better have an offset. */
1149
 
         assert(info->range != VK_WHOLE_SIZE || info->offset > 0);
1150
 
         return true;
1151
 
      }
1152
 
   }
1153
 
   /* Addressing the whole buffer, no custom descriptor needed. */
1154
 
   if (info->range == VK_WHOLE_SIZE ||
1155
 
       info->offset + info->range == info->buffer->size)
1156
 
      return false;
1157
 
   /* We need proper out-of-bounds behavior, we need a descriptor with the right size. */
1158
 
   if (device->vk.enabled_features.robustBufferAccess ||
1159
 
       device->vk.enabled_features.robustBufferAccess2)
1160
 
      return true;
1161
 
   /* We can just apply an offset in the shader */
1162
 
   return false;
1163
 
}
1164
 
 
1165
1134
static void
1166
1135
dzn_bindless_descriptor_set_write_buffer_desc(struct dzn_device *device,
1167
 
                                              struct dxil_spirv_bindless_entry *map,
 
1136
                                              volatile struct dxil_spirv_bindless_entry *map,
1168
1137
                                              uint32_t desc_offset,
1169
1138
                                              const struct dzn_buffer_desc *info)
1170
1139
{
1171
 
   if (!need_custom_buffer_descriptor(device, info)) {
1172
 
      switch (info->type) {
1173
 
      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1174
 
         map[desc_offset].buffer_idx = info->buffer->cbv_bindless_slot;
1175
 
         break;
1176
 
      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1177
 
         map[desc_offset].buffer_idx = info->buffer->uav_bindless_slot;
1178
 
         break;
1179
 
      default:
1180
 
         unreachable("Unexpected descriptor type");
 
1140
   dzn_buffer_get_bindless_buffer_descriptor(device, info, &map[desc_offset]);
 
1141
}
 
1142
 
 
1143
static bool
 
1144
need_custom_buffer_descriptor(struct dzn_device *device, const struct dzn_buffer_desc *info,
 
1145
                              struct dzn_buffer_desc *out_desc)
 
1146
{
 
1147
   *out_desc = *info;
 
1148
   uint32_t upper_bound_default_descriptor;
 
1149
   uint32_t size_align, offset_align;
 
1150
   /* Canonicalize descriptor types for hash/compare, and get size/align info */
 
1151
   switch (info->type) {
 
1152
   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
 
1153
      out_desc->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
 
1154
      FALLTHROUGH;
 
1155
   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
 
1156
      upper_bound_default_descriptor =
 
1157
         MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * sizeof(float) * 4, info->buffer->size);
 
1158
      size_align = offset_align = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
 
1159
      break;
 
1160
   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
 
1161
      out_desc->type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
 
1162
      FALLTHROUGH;
 
1163
   default:
 
1164
      upper_bound_default_descriptor = MIN2(UINT32_MAX, info->buffer->size);
 
1165
      offset_align = D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT;
 
1166
      size_align = 4;
 
1167
      break;
 
1168
   }
 
1169
 
 
1170
   uint64_t upper_bound = info->range == VK_WHOLE_SIZE ?
 
1171
      info->buffer->size :
 
1172
      info->offset + info->range;
 
1173
   /* Addressing the whole buffer, no custom descriptor needed. */
 
1174
   if (upper_bound == upper_bound_default_descriptor)
 
1175
      return false;
 
1176
 
 
1177
   out_desc->range = ALIGN_POT(upper_bound, size_align);
 
1178
   if (out_desc->range <= upper_bound_default_descriptor) {
 
1179
      /* Use a larger descriptor with the hope that we'll be more likely
 
1180
       * to be able to re-use it. The shader is already doing the offset
 
1181
       * add, so there's not really a cost to putting a nonzero value there. */
 
1182
      out_desc->offset = 0;
 
1183
   } else {
 
1184
      /* At least align-down the base offset to ensure that's a valid view to create */
 
1185
      out_desc->offset = (out_desc->offset / offset_align) * offset_align;
 
1186
      out_desc->range -= out_desc->offset;
 
1187
   }
 
1188
   return true;
 
1189
}
 
1190
 
 
1191
static uint32_t
 
1192
hash_buffer_desc(const void *data)
 
1193
{
 
1194
   const struct dzn_buffer_desc *bdesc = data;
 
1195
   /* Avoid any potential padding in the struct */
 
1196
   uint32_t type_hash = _mesa_hash_data(&bdesc->type, sizeof(bdesc->type));
 
1197
   return _mesa_hash_data_with_seed(&bdesc->range, sizeof(bdesc->range) * 2, type_hash);
 
1198
}
 
1199
 
 
1200
static bool
 
1201
compare_buffer_desc(const void *_a, const void *_b)
 
1202
{
 
1203
   const struct dzn_buffer_desc *a = _a, *b = _b;
 
1204
   assert(a->buffer == b->buffer);
 
1205
   /* Avoid any potential padding in the struct */
 
1206
   return a->type == b->type &&
 
1207
          a->range == b->range &&
 
1208
          a->offset == b->offset;
 
1209
}
 
1210
 
 
1211
static int
 
1212
handle_custom_descriptor_cache(struct dzn_device *device,
 
1213
                               const struct dzn_buffer_desc *stack_desc)
 
1214
{
 
1215
   /* Buffer lock is held */
 
1216
 
 
1217
   /* Initialize hash map */
 
1218
   if (!stack_desc->buffer->custom_views)
 
1219
      stack_desc->buffer->custom_views = _mesa_hash_table_create(NULL, hash_buffer_desc, compare_buffer_desc);
 
1220
 
 
1221
   if (!stack_desc->buffer->custom_views)
 
1222
      return -1;
 
1223
 
 
1224
   uint32_t hash = hash_buffer_desc(stack_desc);
 
1225
   struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(stack_desc->buffer->custom_views, hash, stack_desc);
 
1226
   if (entry)
 
1227
      return (int)(intptr_t)entry->data;
 
1228
 
 
1229
   int slot = dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
 
1230
   if (slot < 0)
 
1231
      return slot;
 
1232
 
 
1233
   struct dzn_buffer_desc *key = malloc(sizeof(*stack_desc));
 
1234
   if (!key) {
 
1235
      dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, slot);
 
1236
      return -1;
 
1237
   }
 
1238
 
 
1239
   *key = *stack_desc;
 
1240
   entry = _mesa_hash_table_insert_pre_hashed(stack_desc->buffer->custom_views, hash, key, (void *)(intptr_t)slot);
 
1241
   if (!entry) {
 
1242
      free(key);
 
1243
      dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, slot);
 
1244
      return -1;
 
1245
   }
 
1246
 
 
1247
   dzn_descriptor_heap_write_buffer_desc(device, &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
 
1248
                                         slot, key->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, key);
 
1249
   return slot;
 
1250
}
 
1251
 
 
1252
void
 
1253
dzn_buffer_get_bindless_buffer_descriptor(struct dzn_device *device,
 
1254
                                          const struct dzn_buffer_desc *bdesc,
 
1255
                                          volatile struct dxil_spirv_bindless_entry *out)
 
1256
{
 
1257
   int slot;
 
1258
   uint32_t offset = bdesc->offset;
 
1259
   switch (bdesc->type) {
 
1260
   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
 
1261
   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
 
1262
      slot = bdesc->buffer->cbv_bindless_slot;
 
1263
      break;
 
1264
   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
 
1265
   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
 
1266
      slot = bdesc->buffer->uav_bindless_slot;
 
1267
      break;
 
1268
   default:
 
1269
      unreachable("Unexpected descriptor type");
 
1270
   }
 
1271
 
 
1272
   struct dzn_buffer_desc local_desc;
 
1273
   if (need_custom_buffer_descriptor(device, bdesc, &local_desc)) {
 
1274
      mtx_lock(&bdesc->buffer->bindless_view_lock);
 
1275
 
 
1276
      int new_slot = handle_custom_descriptor_cache(device, &local_desc);
 
1277
      if (new_slot >= 0) {
 
1278
         slot = new_slot;
 
1279
         offset = bdesc->offset - local_desc.offset;
1181
1280
      }
1182
 
      map[desc_offset].buffer_offset = info->offset;
1183
 
      if (*info->bindless_descriptor_slot >= 0)
1184
 
         dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, *info->bindless_descriptor_slot);
1185
 
   } else {
1186
 
      if (*info->bindless_descriptor_slot < 0)
1187
 
         *info->bindless_descriptor_slot =
1188
 
            dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1189
 
      uint32_t offset = (info->offset / D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT) * D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT;
1190
 
 
1191
 
      struct dzn_buffer_desc local_info = *info;
1192
 
      local_info.offset = offset;
1193
 
      info = &local_info;
1194
 
 
1195
 
      dzn_descriptor_heap_write_buffer_desc(device, &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
1196
 
                                            *info->bindless_descriptor_slot, info->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, info);
1197
 
      map[desc_offset].buffer_idx = *info->bindless_descriptor_slot;
1198
 
      map[desc_offset].buffer_offset = info->offset - offset;
 
1281
      /* In the case of cache failure, just use the base view and try
 
1282
       * shader-based offsetting, it'll probably still work in most cases. */
 
1283
 
 
1284
      mtx_unlock(&bdesc->buffer->bindless_view_lock);
1199
1285
   }
 
1286
 
 
1287
   out->buffer_idx = slot;
 
1288
   out->buffer_offset = offset;
1200
1289
}
1201
1290
 
1202
1291
void
1374
1463
   if (dynamic_buffer_idx == ~0)
1375
1464
      return;
1376
1465
 
1377
 
   if (device->bindless) {
1378
 
      if (!need_custom_buffer_descriptor(device, info)) {
1379
 
         if (*info->bindless_descriptor_slot >= 0)
1380
 
            dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, *info->bindless_descriptor_slot);
1381
 
      } else {
1382
 
         if (*info->bindless_descriptor_slot < 0)
1383
 
            *info->bindless_descriptor_slot =
1384
 
            dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1385
 
         uint32_t offset = (info->offset / D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT) * D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT;
1386
 
 
1387
 
         struct dzn_buffer_desc local_info = *info;
1388
 
         local_info.offset = offset;
1389
 
         dzn_descriptor_heap_write_buffer_desc(device, &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
1390
 
                                               *info->bindless_descriptor_slot, info->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &local_info);
1391
 
      }
1392
 
   }
1393
 
 
1394
1466
   assert(dynamic_buffer_idx < set->layout->dynamic_buffers.count);
1395
1467
   set->dynamic_buffers[dynamic_buffer_idx] = *info;
1396
1468
}
1590
1662
{
1591
1663
   vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET);
1592
1664
 
1593
 
   if (device->bindless && layout->buffer_count) {
1594
 
      set->buffer_heap_slots = malloc(sizeof(int) * layout->buffer_count);
1595
 
      if (!set->buffer_heap_slots) {
1596
 
         vk_object_base_finish(&set->base);
1597
 
         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1598
 
      }
1599
 
      memset(set->buffer_heap_slots, 0xff, sizeof(int) * layout->buffer_count);
1600
 
   }
1601
 
 
1602
1665
   set->pool = pool;
1603
1666
   set->layout = layout;
1604
1667
 
1641
1704
dzn_descriptor_set_finish(struct dzn_descriptor_set *set)
1642
1705
{
1643
1706
   vk_object_base_finish(&set->base);
1644
 
   if (set->buffer_heap_slots) {
1645
 
      struct dzn_device *device = container_of(set->base.device, struct dzn_device, vk);
1646
 
      for (uint32_t i = 0; i < set->layout->buffer_count; ++i)
1647
 
         dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
1648
 
                                              set->buffer_heap_slots[i]);
1649
 
   }
1650
 
   free(set->buffer_heap_slots);
1651
 
   set->buffer_heap_slots = NULL;
1652
1707
   set->pool = NULL;
1653
1708
   set->layout = NULL;
1654
1709
}
2126
2181
         struct dzn_buffer_desc desc = {
2127
2182
            pDescriptorWrite->descriptorType,
2128
2183
            dzn_buffer_from_handle(binfo->buffer),
2129
 
            binfo->range, binfo->offset,
2130
 
            &set->buffer_heap_slots[dzn_descriptor_set_ptr_get_buffer_idx(set->layout, &ptr)]
 
2184
            binfo->range, binfo->offset
2131
2185
         };
2132
2186
 
2133
2187
         if (desc.buffer)
2146
2200
         struct dzn_buffer_desc desc = {
2147
2201
            pDescriptorWrite->descriptorType,
2148
2202
            dzn_buffer_from_handle(binfo->buffer),
2149
 
            binfo->range, binfo->offset,
2150
 
            &set->buffer_heap_slots[dzn_descriptor_set_ptr_get_buffer_idx(set->layout, &ptr)]
 
2203
            binfo->range, binfo->offset
2151
2204
         };
2152
2205
 
2153
2206
         if (desc.buffer)
2236
2289
            dst_heap_offset += dst_set->heap_offsets[type];
2237
2290
 
2238
2291
            if (device->bindless) {
2239
 
               memcpy(&dst_set->pool->bindless.map[dst_heap_offset],
2240
 
                      &src_set->pool->bindless.map[src_heap_offset],
 
2292
               memcpy((void *)&dst_set->pool->bindless.map[dst_heap_offset],
 
2293
                      (const void *)&src_set->pool->bindless.map[src_heap_offset],
2241
2294
                      sizeof(src_set->pool->bindless.map[0]) * count);
2242
2295
               /* There's never a reason to loop and memcpy again for bindless */
2243
2296
               break;
2512
2565
            struct dzn_buffer_desc desc = {
2513
2566
               entry->type,
2514
2567
               dzn_buffer_from_handle(info->buffer),
2515
 
               info->range, info->offset,
2516
 
               &set->buffer_heap_slots[entry->buffer_idx],
 
2568
               info->range, info->offset
2517
2569
            };
2518
2570
 
2519
2571
            if (desc.buffer)
2532
2584
            struct dzn_buffer_desc desc = {
2533
2585
               entry->type,
2534
2586
               dzn_buffer_from_handle(info->buffer),
2535
 
               info->range, info->offset,
2536
 
               &set->buffer_heap_slots[entry->buffer_idx]
 
2587
               info->range, info->offset
2537
2588
            };
2538
2589
 
2539
2590
            if (desc.buffer)