return data;
}
+static unsigned
+anv_descriptor_data_size(enum anv_descriptor_data data)
+{
+ return 0;
+}
+
+/** Returns the size in bytes of each descriptor with the given layout */
+unsigned
+anv_descriptor_size(const struct anv_descriptor_set_binding_layout *layout)
+{
+ return anv_descriptor_data_size(layout->data);
+}
+
+/** Returns the size in bytes of each descriptor of the given type
+ *
+ * This version of the function does not have access to the entire layout so
+ * it may only work on certain descriptor types where the descriptor size is
+ * entirely determined by the descriptor type. Whenever possible, code should
+ * use anv_descriptor_size() instead.
+ */
+unsigned
+anv_descriptor_type_size(const struct anv_physical_device *pdevice,
+ VkDescriptorType type)
+{
+ return anv_descriptor_data_size(anv_descriptor_data_for_type(pdevice, type));
+}
+
void anv_GetDescriptorSetLayoutSupport(
VkDevice device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
uint32_t buffer_view_count = 0;
uint32_t dynamic_offset_count = 0;
+ uint32_t descriptor_buffer_size = 0;
for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[j];
break;
}
+ set_layout->binding[b].descriptor_offset = descriptor_buffer_size;
+ descriptor_buffer_size += anv_descriptor_size(&set_layout->binding[b]) *
+ binding->descriptorCount;
+
set_layout->shader_stages |= binding->stageFlags;
}
set_layout->buffer_view_count = buffer_view_count;
set_layout->dynamic_offset_count = dynamic_offset_count;
+ set_layout->descriptor_buffer_size = descriptor_buffer_size;
*pSetLayout = anv_descriptor_set_layout_to_handle(set_layout);
SHA1_UPDATE_VALUE(ctx, layout->descriptor_index);
SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_index);
SHA1_UPDATE_VALUE(ctx, layout->buffer_view_index);
+ SHA1_UPDATE_VALUE(ctx, layout->descriptor_offset);
if (layout->immutable_samplers) {
for (uint16_t i = 0; i < layout->array_size; i++)
SHA1_UPDATE_VALUE(ctx, layout->shader_stages);
SHA1_UPDATE_VALUE(ctx, layout->buffer_view_count);
SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count);
+ SHA1_UPDATE_VALUE(ctx, layout->descriptor_buffer_size);
for (uint16_t i = 0; i < layout->binding_count; i++)
sha1_update_descriptor_set_binding_layout(ctx, &layout->binding[i]);
* and the free lists lets us recycle blocks for case 2).
*/
+/* The vma heap reserves 0 to mean NULL; we have to offset by some ammount to
+ * ensure we can allocate the entire BO without hitting zero. The actual
+ * amount doesn't matter.
+ */
+#define POOL_HEAP_OFFSET 64
+
#define EMPTY 1
VkResult anv_CreateDescriptorPool(
uint32_t descriptor_count = 0;
uint32_t buffer_view_count = 0;
+ uint32_t descriptor_bo_size = 0;
for (uint32_t i = 0; i < pCreateInfo->poolSizeCount; i++) {
enum anv_descriptor_data desc_data =
anv_descriptor_data_for_type(&device->instance->physicalDevice,
if (desc_data & ANV_DESCRIPTOR_BUFFER_VIEW)
buffer_view_count += pCreateInfo->pPoolSizes[i].descriptorCount;
+ unsigned desc_data_size = anv_descriptor_data_size(desc_data) *
+ pCreateInfo->pPoolSizes[i].descriptorCount;
+ descriptor_bo_size += desc_data_size;
+
descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount;
}
+ /* We have to align descriptor buffer allocations to 32B so that we can
+ * push descriptor buffers. This means that each descriptor buffer
+ * allocated may burn up to 32B of extra space to get the right alignment.
+ * (Technically, it's at most 28B because we're always going to start at
+ * least 4B aligned but we're being conservative here.) Allocate enough
+ * extra space that we can chop it into maxSets pieces and align each one
+ * of them to 32B.
+ */
+ descriptor_bo_size += 32 * pCreateInfo->maxSets;
+ descriptor_bo_size = ALIGN(descriptor_bo_size, 4096);
const size_t pool_size =
pCreateInfo->maxSets * sizeof(struct anv_descriptor_set) +
pool->next = 0;
pool->free_list = EMPTY;
+ if (descriptor_bo_size > 0) {
+ VkResult result = anv_bo_init_new(&pool->bo, device, descriptor_bo_size);
+ if (result != VK_SUCCESS) {
+ vk_free2(&device->alloc, pAllocator, pool);
+ return result;
+ }
+
+ anv_gem_set_caching(device, pool->bo.gem_handle, I915_CACHING_CACHED);
+
+ pool->bo.map = anv_gem_mmap(device, pool->bo.gem_handle, 0,
+ descriptor_bo_size, 0);
+ if (pool->bo.map == NULL) {
+ anv_gem_close(device, pool->bo.gem_handle);
+ vk_free2(&device->alloc, pAllocator, pool);
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ }
+
+ if (device->instance->physicalDevice.use_softpin) {
+ pool->bo.flags |= EXEC_OBJECT_PINNED;
+ anv_vma_alloc(device, &pool->bo);
+ }
+
+ util_vma_heap_init(&pool->bo_heap, POOL_HEAP_OFFSET, descriptor_bo_size);
+ } else {
+ pool->bo.size = 0;
+ }
+
anv_state_stream_init(&pool->surface_state_stream,
&device->surface_state_pool, 4096);
pool->surface_state_free_list = NULL;
if (!pool)
return;
+ if (pool->bo.size) {
+ anv_gem_munmap(pool->bo.map, pool->bo.size);
+ anv_vma_free(device, &pool->bo);
+ anv_gem_close(device, pool->bo.gem_handle);
+ }
anv_state_stream_finish(&pool->surface_state_stream);
vk_free2(&device->alloc, pAllocator, pool);
}
pool->next = 0;
pool->free_list = EMPTY;
+
+ if (pool->bo.size) {
+ util_vma_heap_finish(&pool->bo_heap);
+ util_vma_heap_init(&pool->bo_heap, POOL_HEAP_OFFSET, pool->bo.size);
+ }
+
anv_state_stream_finish(&pool->surface_state_stream);
anv_state_stream_init(&pool->surface_state_stream,
&device->surface_state_pool, 4096);
if (result != VK_SUCCESS)
return result;
+ if (layout->descriptor_buffer_size) {
+ /* Align the size to 32 so that alignment gaps don't cause extra holes
+ * in the heap which can lead to bad performance.
+ */
+ uint64_t pool_vma_offset =
+ util_vma_heap_alloc(&pool->bo_heap,
+ ALIGN(layout->descriptor_buffer_size, 32), 32);
+ if (pool_vma_offset == 0) {
+ anv_descriptor_pool_free_set(pool, set);
+ return vk_error(VK_ERROR_FRAGMENTED_POOL);
+ }
+ assert(pool_vma_offset >= POOL_HEAP_OFFSET &&
+ pool_vma_offset - POOL_HEAP_OFFSET <= INT32_MAX);
+ set->desc_mem.offset = pool_vma_offset - POOL_HEAP_OFFSET;
+ set->desc_mem.alloc_size = layout->descriptor_buffer_size;
+ set->desc_mem.map = pool->bo.map + set->desc_mem.offset;
+
+ set->desc_surface_state = anv_descriptor_pool_alloc_state(pool);
+ anv_fill_buffer_surface_state(device, set->desc_surface_state,
+ ISL_FORMAT_R32G32B32A32_FLOAT,
+ (struct anv_address) {
+ .bo = &pool->bo,
+ .offset = set->desc_mem.offset,
+ },
+ layout->descriptor_buffer_size, 1);
+ } else {
+ set->desc_mem = ANV_STATE_NULL;
+ set->desc_surface_state = ANV_STATE_NULL;
+ }
+
+ set->pool = pool;
set->layout = layout;
anv_descriptor_set_layout_ref(layout);
{
anv_descriptor_set_layout_unref(device, set->layout);
+ if (set->desc_mem.alloc_size) {
+ util_vma_heap_free(&pool->bo_heap,
+ (uint64_t)set->desc_mem.offset + POOL_HEAP_OFFSET,
+ set->desc_mem.alloc_size);
+ anv_descriptor_pool_free_state(pool, set->desc_surface_state);
+ }
+
for (uint32_t b = 0; b < set->buffer_view_count; b++)
anv_descriptor_pool_free_state(pool, set->buffer_views[b].surface_state);
for (uint32_t j = 0; j < copy->descriptorCount; j++)
dst_desc[j] = src_desc[j];
+
+ unsigned desc_size = anv_descriptor_size(src_layout);
+ if (desc_size > 0) {
+ assert(desc_size == anv_descriptor_size(dst_layout));
+ memcpy(dst->desc_mem.map + dst_layout->descriptor_offset +
+ copy->dstArrayElement * desc_size,
+ src->desc_mem.map + src_layout->descriptor_offset +
+ copy->srcArrayElement * desc_size,
+ copy->descriptorCount * desc_size);
+ }
}
}