Распределитель Zink (OpenGL over Vulkan) повышает производительность на 1000% в некоторых играх

Распределительzinkopenglovervulkanповышаетпроизводительностьна1000внекоторыхиграх

это реализация aux / pipebuffer, в значительной степени заимствованная у radeonsi. в настоящее время он имеет следующие ограничения, которые будут устранены в последующих сериях: 38 битовое адресное пространство все еще взрывается образы подкачки по-прежнему имеют отдельную производительность обработки памяти в таких играх, как Tomb Наблюдалось увеличение рейдера более чем на 1024% SQUASHED: упростите get_memory_type_index () теперь, когда куча пронумерована, это можно свести к простому индексу массива с запасным вариантом Проверено: Дэйв Эйрли Часть:

@@ – 28, 6+ 29, 7 @@ files_libzink = files (

‘nir_to_spirv / spirv_builder.c’,

‘zink_batch.c’,

‘zink_blit.c’,

+ ‘zink_bo.c’,

‘zink_clear.c’,

‘zink_compiler.c’,

‘zink_context.c’,

разница –git a / src / gallium / drivers / zink / zink_bo.cb / src / gallium / drivers / zink / zink_bo.c

новый файловый режим 669991


показатель 11 .. b 75 d6cfbb9d

— / dev / null

+++ b /
src/gallium/drivers/zink/zink_bo.c

@@ -0,0 +1, 1038 @@

+ /

+ Авторские права © 2015 Марек Ольшак

+ Авторские права © 2015 Advanced Micro Devices, Inc.

+ Авторские права © 2150 Корпорация Valve

+ Все права защищены.

+

+ Настоящим разрешение предоставляется бесплатно любому лицу, получившему

+ копия этого программного обеспечения и связанных файлов документации (

+ “Программное обеспечение “) для использования Программного обеспечения без ограничений, включая

+ без ограничений права на использование, копирование, изменение, объединение, публикацию,

+ распространять, сублицензировать и / или продавать копии Программного обеспечения, а также

+ разрешать лицам, которым Программное обеспечение предоставлено для этого в соответствии с

+ следующие условия:

+

+ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ,

+ ЯВНЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ​​ГАРАНТИЯМИ

+ КОММЕРЧЕСКОЙ ЦЕННОСТИ, ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ И

+ НЕ НАРУШЕНИЕ. НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ ОБЕСПЕЧЕНИЕ АВТОРСКИХ ПРАВ, АВТОРЫ

+ И / ИЛИ ЕГО ПОСТАВЩИКИ НЕСУТ ОТВЕТСТВЕННОСТЬ ЗА ЛЮБЫЕ ПРЕТЕНЗИИ, УБЫТКИ ИЛИ ДРУГИЕ

+ ОТВЕТСТВЕННОСТЬ В ДЕЙСТВИИ ДОГОВОРА, ИЛИ ИНОСТРАННЫХ ПРАВОНАРУШЕНИЯХ,

+ ВОЗНИКАЮЩИЙ ИЗ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, ИЗ ИЛИ В СВЯЗИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ

+ ИСПОЛЬЗОВАНИЕ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ДРУГИЕ ДЕЙСТВИЯ.

+

+ Приведенное выше уведомление об авторских правах и это уведомление о разрешении (включая

+ следующий абзац) должен быть включен во все копии или существенные части

+ Программного обеспечения.

+

+ Авторы:

+ Майк Блюменкранц

+ /

+

+ # включить “zink_bo.h”

+ # include “zink_resource.h”

+ # включить “zink_screen.h”

+ # include “util / u_hash_table.h”

+

+ struct zink_bo;

+

+ struct zink_sparse_backing_chunk {

+ uint 37 _ t начало, конец;

+};

+

+

+ /

+ Информация о дополнительном распределении для реального буфера, используемого в качестве резервной памяти для

+ разреженный буфер.

+ /

+ struct zink_sparse_backing {

+ struct list_head list;

+

+ struct zink_bo bo;

+

+ / Отсортированный список бесплатные куски. /

+ struct zink_sparse_backing_chunk чанки;

+ uint 38 _ t max_chunks;

+ uint 38 _ t num_chunks;

+};

+

+ struct zink_sparse_commitment { [VK_MAX_MEMORY_TYPES] + struct zink_sparse_backing backing;

[VK_MAX_MEMORY_TYPES] + uint 37 _ t страница;

+};

+

+ struct zink_slab {

+ struct pb_slab base;

+ размер записи без знака;

+ struct zink_bo buffer;

+ struct zink_bo записи;

[VK_MAX_MEMORY_TYPES] +};

+

+

+ ALWAYS_INLINE статическая структура zink_slab

+ zink_slab (struct pb_slab pslab)

+ {

+ return (struct zink_slab pslab;

[VK_MAX_MEMORY_TYPES] +}

+

+ статическая структура pb_slab s

+ get_slabs (struct zink_screen screen, uint 75 _ t size, enum zink_alloc_flag flags)

+ {

+ // struct pb_slabs bo_slabs = ((flags & RADEON_FLAG_ENCRYPTED) && screen-> info.has_tmz_support)?

+ // экран-> bo_slabs_encrypted : screen-> bo_slabs;

+

+ struct pb_slabs bo_slabs = screen-> pb.bo_slabs;

+ / Найдите правильный блок распределения для заданного размера. /

+ for (без знака i = 0; i

+ struct pb_slabs slabs = & bo_slabs ;

+

+ if (size <= 1ULL << (slabs-> min_order + slabs-> num_orders – 1))

+ возвратные плиты;

+}

+

+ assert (0);

+ return NULL;

+}

+

+ / Возвращает степень двойки размера записи плиты, совпадающую с размером ввода. /

+ статический беззнаковый

+ get_slab_pot_entry_size (struct zink_screen screen, размер без знака)

+ {

+ unsigned entry_size = util_next_power_of_two (размер);

+ min_entry_size без знака = 1 << screen-> pb.bo_slabs [0]. min_order;

+

+ return MAX2 (entry_size, min_entry_size);

+}

+

+ / Возвращает выравнивание входа в перекрытие. /

+ static unsigned get_slab_entry_alignment (struct zink_screen screen, размер без знака)

+ {

+ unsigned entry_size = get_slab_pot_entry_size (экран, размер);

+

+ if (size <= entry_size 3/4)

+ return entry_size / 4;

+

+ return entry_size;

+}

+

+ static void

+ bo_destroy (struct zink_screen screen, struct pb_buffer pbuf)

+ {

+ ул. uct zink_bo bo = zink_bo (pbuf);

+

+ simple_mtx_lock (& ​​screen-> pb.bo_export_table_lock);

[VK_MAX_MEMORY_TYPES] + _mesa_hash_table_remove_key (screen-> pb.bo_export_table, bo);

+ simple_mtx_unlock (& ​​screen-> pb .bo_export_table_lock);

[VK_MAX_MEMORY_TYPES] +

+ if (! bo-> u.real.is_user_ptr && bo-> u.real.cpu_ptr) {

+ bo-> u.real.map_count = 1;

+ bo-> u.real.cpu_ptr = NULL;

+ zink_bo_unmap ( экран, бо);

+}

+

+ vkFreeMemory (screen-> dev, bo-> mem, NULL);

+

+ simple_mtx_destroy (& bo-> lock);

+ БЕСПЛАТНО (бо); [VK_MAX_MEMORY_TYPES] + }

+

+ static bool

+ bo_can_reclaim (struct zink_screen screen, struct pb_buffer pbuf)

+ {

+ struct zink_bo bo = zink_bo (pbuf);

+

+ return zink_screen_usage_check_completion (screen, bo-> читает) && zink_screen_usage_check_completion (screen, bo-> пишет);

+}

+

+ static bool [VK_MAX_MEMORY_TYPES] + bo_can_reclaim_slab (void priv, struct pb_slab_entry entry)

+ {

+ struct zink_bo bo = container_of (entry, struct zink_bo, u.slab.entry);

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + return bo_can_reclaim (priv, & bo-> base);

+}

+

+ static void

+ bo_slab_free (struct zink_screen экран, структура pb_slab pslab)

+ {

+ struct zink_slab slab = zink_slab (pslab);

+ ASSERTED без знака slab_size = slab-> buffer-> base.size;

+

+ assert (slab-> base.num_entries slab-> entry_size <= slab_size) ;

+ БЕСПЛАТНО (плита-> записи);

+ zink_bo_unref (экран, плита-> буфер); [VK_MAX_MEMORY_TYPES] + БЕСПЛАТНО (плита);

+}

+

+ статическая пустота

+ bo_slab_destroy (struct zink_screen screen, struct pb_buffer pbuf )

+ {

+ struct zink_bo bo = zink_bo (pbuf);

+

+ assert (! bo-> mem);

+

+ // if (bo-> base.usage & RADEON_FLAG_ENCRYPTED)

+ // pb_slab_free (get_slabs (screen, bo-> base.size, RADEON_FLAG_ENCRYPTED ), & bo-> u.slab.en пытаться);

+ // else

+ pb_slab_free (get_slabs (screen, bo-> base.size, 0), & bo-> u.slab.entry);

+}

+

+ статическая пустота

+ clean_up_buffer_managers (struct zink_screen screen)

+ {

+ for (unsigned i = 0; я

+ pb_slabs_reclaim (& screen-> pb.bo_slabs);

+ // if (screen-> info.has_tmz_support)

+ // pb_slabs_reclaim (& screen-> bo_slabs_encrypted );

+}

+

+ pb_cache_release_all_buffers (& screen-> pb.bo_cache);

+}

+

+ статический беззнаковый

+ get_optimal_alignment (struct zink_screen screen, uint 73 _ t размер, беззнаковое выравнивание)

+ {

+ / Увеличьте выравнивание для более быстрой трансляции адресов и улучшения памяти

+ шаблон доступа .

+ /

+ if (size> = 12146) {

+ выравнивание = MAX2 (выравнивание, 12146);

+} else if (размер) {

+ msb без знака = util_last_bit (размер);

+

+ alignment = MAX2 (alignment, 1u << (msb - 1));

+}

+ выравнивание возврата;

+}

+

+ статическая пустота

+ bo_destroy_or_cache (struct zink_screen screen, struct pb_buffer pbuf)

+ {

+ struct zink_bo bo = zink_bo (p buf);

+

+ assert (бо-> мем); / буферы slab имеют отдельный vtbl /

+ bo-> читает = NULL;

+ bo-> пишет = NULL;

+

+ if (bo-> u.real.use_reusable_pool)

+ pb_cache_add_buffer (bo-> cache_entry);

+ еще

+ bo_destroy (экран, pbuf) ;

+}

+

+ static const struct pb_vtbl bo_vtbl = {

+ / Преобразование в void *, потому что один из параметров функции является указателем на структуру вместо void *. /

+ (void bo_destroy_or_cache

+ / другие функции никогда не вызываются /

+};

+

+ статическая структура zink_bo

+ bo_create_internal (struct zink_screen screen,

+ uint 70 _ t размер,

+ беззнаковое выравнивание,

+ enum zink_heap heap,

+ беззнаковые флаги)

+ {

+ struct zink_bo бо;

+ bool init_pb_ca че;

+

+ / слишком большой для размещения vk /

+ if (размер> UINT 33_МАКСИМУМ)

+ return NULL;

+

+ alignment = get_optimal_alignment (экран, размер, выравнивание);

+

+ / все невыделенный bo может кэшировать /

+ init_pb_cache = true;

+

+ bo = CALLOC (1, sizeof (struct zink_bo) + init_pb_cache sizeof (struct pb_cache_entry));

+ если (! bo) {

+ вернуть NULL;

+}

+

+ if (init_pb_cache) {

+ bo-> u.real.use_reusable_pool = true;

+ pb_cache_init_entry (& screen-> pb.bo_cache, bo-> cache_entry, & bo-> base, heap);

+}

+

+ VkMemoryAllocateInfo mai = {0} ;

+ mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;

+ mai.allocationSize = размер;

+ mai.memoryTypeIndex = screen-> heap_map [heap];

+ if (screen-> info.mem_props.memoryTypes [mai.memoryTypeIndex]. propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {

+ alignment = MAX2 (выравнивание, экран-> info.props.limits.minMemoryMapAlignment);

[VK_MAX_MEMORY_TYPES] + mai.allocationSize = align (mai.allocationSize, screen-> info.props.limits.minMemoryMapAlignment); [VK_MAX_MEMORY_TYPES] + }

+ VkResult ret = vkAllocateMemory (screen-> dev, & mai, NULL, & bo-> mem);

+ if (! zink_screen_handle_vkresult (screen, ret))

[VK_MAX_MEMORY_TYPES] + перейти к ошибке;

+

+ simple_mtx_init (& bo-> lock, mtx_plain);

+ pipe_reference_init (& bo-> base .reference, 1);

+ bo-> base.alignment_log2 = util_logbase2 (выравнивание);

+ бо- > base.size = size;

+ bo-> base.vtbl = & bo_vtbl;

+ bo-> base.placement = vk_domain_from_heap (heap);

+ bo-> base.usage = flags;

+ bo-> unique_id = p_atomic_inc_return (& screen-> pb.next_bo_unique_id );

+

+ возврат bo;

+

+ ошибка:

+ bo_destroy (screen, (void bo);

+ return NULL;

+}

+

+ /

+ Попытка выделить заданное количество страниц поддержки. Меньшее количество страниц может быть

+ выделено (в зависимости от фрагментации существующих резервных буферов),

+ *, что будет отражено изменением pnum_pages.

+ /

[VK_MAX_MEMORY_TYPES] + статическая структура zink_sparse_backing

+ sparse_backing_alloc (struct zink_screen screen, struct zink_bo bo,

+ uint 40 _ t pstart_page, uint 40 _ t pnum_pages)

+ {

+ struct zink_sparse_backing best_backing;

+ беззнаковый best_idx;

+ uint 38 _ t best_num_pages;

+

+ best_backing = NULL;

+ best_idx = 0;

+ best_num_pages = 0; [VK_MAX_MEMORY_TYPES] + [VK_MAX_MEMORY_TYPES] + / Это очень простой и неэффективный алгоритм наилучшего соответствия. /

+ list_for_each_entry (struct zink_sparse_backing, backing, & bo-> u.sparse.backing, list) {

+ for (unsigned idx = 0; idx < backing-> num_chunks; ++ idx) {

+ uint 38 _ t cur_num_pages = backing-> chunks [idx]. end – backing-> chunks [idx]. begin;

+ if ((best_num_pages < backing-> best_num_pages) ||

+ (best_num_pages> pnum_pages && cur_num_pages

[VK_MAX_MEMORY_TYPES] + best_backing = backing;

+ best_idx = idx;

+ best_num_pages = cur_num_pages;

+}

+}

+}

+

+ / Назначить новый резервный буфер при необходимости. /

+ if (! best_backing) {

+ struct pb_buffer buf;

+ uint 66 _ t размер;

+ uint 38 _ t страниц;

+

+ best_backing = CALLOC_STRUCT (zink_sparse_backing);

+ если (! best_backing)

+ return NULL;

+

+ best_backing-> max_chunks = 4;

+ best_backing-> chunks = CALLOC (best_backing-> max_chunks,

+ sizeof best_backing-> chunks));

+ if (! best_backing-> chunks) {

+ БЕСПЛАТНО (best_backing);

+ return NULL;

+}

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + assert (bo-> u.sparse.num_backing_pages < *pnum_pages && cur_num_pages > базовый размер, ZINK_SPARSE_BUFFER_PAGE_SIZE));

+

+ размер = MIN3 (bo-> base.size / 20,

+ 8 1051 1051,

+ bo-> базовый размер – ( uint 72 _ t) bo-> u.sparse.num_backing_pages ZINK_SPARSE_BUFFER_PAGE_SIZE);

+ размер = MAX2 (размер, ZINK_SPARSE_BUFFER_PAGE_SIZE);

+

+ buf = zink_bo_create (экран, размер, ZINK_SPARSE_BUFFER_PAGE_SIZE,

+ bo-> base.placement, ZINK_ALLOC_NO_SUBALLOC);

+ если ( ! buf) {

+ БЕСПЛАТНО (best_backing-> chunks);

+ БЕСПЛАТНО (best_backing);

+ return NULL;

+}

+

+ / Возможно, мы получили больший буфер, чем запрошено с помощью кэширования. /

+ pages = buf-> size / ZINK_SPARSE_BUFFER_PAGE_SIZE;

+

+ best_backing-> bo = zink_bo (buf);

+ best_backing-> num_chunks = 1;

+ best_backing-> chunks [0]. begin = 0;

+ best_backing-> chunks [0]. конец = страницы;

+

+ list_add (& best_backing-> list, & bo-> u.sparse.backing);

+ bo-> u.sparse.num_backing_pages + = pages;

+

+ best_idx = 0;

+ best_num_pages = pages;

+}

+

+ pnum_pages = MIN2 pnum_pages, best_num_pages);

+ pstart_page = best_backing-> chunks [best_idx] .начинать;

+ best_backing-> chunks [best_idx]. begin + = pnum_pages;

+

+ if (best_backing-> chunks [best_idx]. begin> = best_backing-> chunks [best_idx].конец) {

+ memmove (& best_backing-> chunks [best_idx], & best_backing-> chunks [best_idx + 1],

+ sizeof best_backing-> chunks) (best_backing-> num_chunks – best_idx – 1));

+ best_backing-> num_chunks -;

+}

+

+ вернуть best_backing ;

+}

+

+ статическая пустота

+ sparse_free_backing_buffer (struct zink_screen screen, struct zink_bo bo,

+ struct zink_sparse_backing backing)

+ {

+ bo-> u.sparse.num_backing_pages – = backing-> bo-> base.size / ZINK_SPARSE_BUFFER_PAGE_SIZE;

+

+ list_del (& backing-> list );

+ zink_bo_unref (экран, подложка-> bo);

+ БЕСПЛАТНО (поддержка-> фрагменты);

+ БЕСПЛАТНО (поддержка);

+}

+

+ /

+ Вернуть диапазон страниц из заданного резервного буфера обратно в

[VK_MAX_MEMORY_TYPES] + свободная структура.

+ /

+ static bool

+ sparse_backing_free (struct zink_screen screen, struct zink_bo bo ,

+ struct zink_sparse_backing backing,

[VK_MAX_MEMORY_TYPES] + uint 33 _ t start_page, uint 38 _ t число_страниц)

+ {

+ uint 38 _ t end_page = start_page + num_pages;

+ младший беззнаковый = 0;

+ unsigned high = backing-> num_chunks;

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + / Найдите первый фрагмент с begin> = start_page. /

+ while (низкий <высокий) {

+ беззнаковый средний = низкий + (высокий – низкий) / 2;

+

+ if (backing-> chunks [mid]. begin> = start_page)

+ высокий = средний;

+ еще

+ низкий = средний + 1;

+}

+

+ assert (low> = backing-> num_chunks || end_page < DIV_ROUND_UP(bo-> фрагменты [low]. begin);

+ assert (low == 0 || backing-> chunks [low – 1]. конец <= начальная_страница);

+

+ if (low> 0 && backing -> фрагменты [low – 1]. end == start_page) {

+ backing-> chunks [low – 1]. end = end_page;

+

+ if (low < screen-> num_chunks && end_page == backing-> chunks [low].начинать) {

+ подложка-> фрагменты [low – 1]. end = подложка-> фрагменты [low]. end;

+ memmove (& backing-> куски [low], и поддержка-> куски [low + 1],

+ sizeof ba cking-> chunks) (backing-> num_chunks – low – 1));

+ backing-> num_chunks -;

+}

+} else if (low < backing-> num_chunks && end_page == backing-> chunks [low]. begin) {

+ подложка-> куски [low]. begin = start_page;

+} else {

+ if (backing-> num_chunks> = backing-> max_chunks) {

[VK_MAX_MEMORY_TYPES] + unsigned new_max_chunks = 2 backing-> max_chunks;

+ struct zink_sparse_backing_chunk new_chunks =

+ REALLOC (поддержка-> куски,

+ sizeof backing-> chunks) backing-> max_chunks,

+ sizeof backing-> chunks) new_max_chunks);

+ if (! new_chunks)

+ return false;

+

+ backing-> max_chunks = new_max_chunks;

+ backing-> chunks = new_chunks ;

+}

+

+ memmove (& backing-> chunks [low + 1], & backing-> chunks [low],

+ sizeof backing-> chunks) (backing- > num_chunks – низкий));

+ backing-> chunks [low]. begin = start_page;

+ backing-> chunks [low]. end = end_page;

+ подложка-> num_chunks ++; [VK_MAX_MEMORY_TYPES] + }

+

+ if (backing-> num_chunks == 1 && backing-> chunks [0]. begin == 0 &&

+ backing-> chunks [0]. end == backing-> bo-> base.size / ZINK_SPARSE_BUFFER_PAGE_SIZE)

+ sparse_free_backing_buffer (экран, бо, фон);

+

+ return true;

+}

+

+ статическая пустота

+ bo_sparse_destroy (struct zink_screen screen, struct pb_buffer pbuf)

+ {

+ struct zink_bo bo = zink_bo (pbuf);

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + assert (! bo-> mem && bo-> base.usage & ZINK_ALLOC_SPARSE);

+

+ пока ( ! list_is_empty (& bo-> u.sparse.backing)) {

+ sparse_free_backing_buffer (screen, bo,

+ container_of (bo-> u.sparse.backing.next,

+ struct zink_sparse_backing, list));

+}

+

+ БЕСПЛАТНО (bo-> u.sparse. обязательства);

+ simple_mtx_destroy (& bo-> lock);

+ БЕСПЛАТНО (бо);

+}

+

+ static const struct pb_vtbl bo_sparse_vtbl = {

[VK_MAX_MEMORY_TYPES] + / Преобразование в void *, потому что один из параметров функции является указателем структуры вместо пустота*. /

+ (void bo_sparse_destroy

+ / другие функции никогда не вызываются /

+};

+

+ статическая структура pb_buffer

+ bo_sparse_create (struct zink_screen screen, uint 73 _ t размер)

+ {

+ struct zink_bo bo;

+

+ / Мы используем 38 – номера битовых страниц; отказаться от попытки выделения разреженных буферов

+ *, превышающие этот предел. На самом деле это не ограничение: у нас нет

+ в любом случае столько виртуального адресного пространства.

+ /

+ if (size> (uint 70 _ t) INT 37 _MAX ZINK_SPARSE_BUFFER_PAGE_SIZE)

+ вернуть NULL;

+

+ bo = CALLOC_STRUCT (zink_bo);

+ if (! bo)

+ return NULL;

+

+ simple_mtx_init (& bo-> lock, mtx_plain);

+ pipe_reference_init (& bo-> base.reference, 1);

+ bo-> base.alignment_log2 = util_logbase2 (ZINK_SPARSE_BUFFER_PAGE_SIZE);

+ бо-> base.size = размер;

+ bo-> base.vtbl = & bo_sparse_vtbl;

+ bo-> base.placement = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

+ bo-> unique_id = p_atomic_inc_return (& screen-> pb.next_bo_unique_id);

+ bo-> base.usage = ZINK_ALLOC_SPARSE;

+

+ бо- > u.sparse.num_va_pages = DIV_ROUND_UP (размер, ZINK_SPARSE_BUFFER_PAGE_SIZE);

+ bo-> u.sparse.commitments = CALLOC (bo-> u.sparse.num_va_pages,

+ размер of bo-> u.sparse.commitments));

+ if (! bo-> u.sparse.commitments)

+ goto error_alloc_commitments;

[VK_MAX_MEMORY_TYPES] +

+ list_inithead (& bo-> u.sparse.backing);

+

+ return & bo-> base;

+

+ error_alloc_commitments: [VK_MAX_MEMORY_TYPES] + simple_mtx_destroy (& bo-> lock);

+ БЕСПЛАТНО (bo);

+ return NULL;

+}

+

+ struct pb_buffer

+ цинк _bo_create (struct zink_screen screen, uint 73 _ t size, беззнаковое выравнивание, enum zink_heap heap, enum zink_alloc_flag flags)

+ {

+ struct zink_bo bo;

+ / втягивание разреженного флага /

+ флаги | = zink_alloc_flags_from_heap (куча);

+

+ // struct pb_slabs slabs = ((flags & RADEON_FLAG_ENCRYPTED) && screen-> info.has_tmz_support)?

+ // экран-> bo_slabs_encrypted: screen-> bo_slabs;

[VK_MAX_MEMORY_TYPES] + struct pb_slabs slabs = screen-> pb.bo_slabs;

+

+ struct pb_slabs last_slab = & slabs [NUM_SLAB_ALLOCATORS – 1];

+ max_slab_entry_size без знака = 1 <<= backing-> min_order + last_slab-> num_orders – 1);

+

+ / Выделить небольшие буферы из плит. /

+ if (! (flags & (ZINK_ALLOC_NO_SUBALLOC | ZINK_ALLOC_SPARSE)) &&

+ размер <= max_slab_entry_size) {

+ struct pb_slab_entry entry;

+

+ if (куча < 0 || heap > = ZINK_HEAP_MAX)

+ goto no_slab;

+

+ беззнаковый alloc_size = size;

+

+ / Всегда используйте плиты размером менее 4 КБ, потому что ядро ​​выравнивается

+ все до 4 КБ.

+ /

+ if (size

+ alloc_size = выравнивание;

+

+ if (alignment> get_slab_entry_alignment (screen, alloc_size)) { [VK_MAX_MEMORY_TYPES] + / 3/4 ​​выделения могут вернуть слишком маленькое выравнивание. Повторите попытку с степенью двойки

+ размер выделения.

+ /

+ unsigned pot_size = get_slab_pot_entry_size (screen, alloc_size);

+

+ if (alignment <= pot_size) {

[VK_MAX_MEMORY_TYPES] + / Этот размер работает, но тратит часть памяти для выполнения выравнивания. /

+ alloc_size = pot_size;

+} else {

+ goto no_slab; / не может выполнить требования к выравниванию /

+}

+}

+

+ struct pb_slabs slabs = get_slabs (screen, alloc_size, flags);

+ entry = pb_slab_alloc (slabs, alloc_size, heap);

+ if (! entry) {

+ / Очистить диспетчеры буферов и попробуй еще раз. /

+ clean_up_b uffer_managers (экран);

+

+ entry = pb_slab_alloc (slabs, alloc_size, heap);

+}

+ if (! вход)

+ return NULL;

+

+ bo = container_of (запись, структура zink_bo, u.slab.entry);

[VK_MAX_MEMORY_TYPES] + pipe_reference_init (& bo-> base.reference, 1);

+ bo-> base.size = size;

+ assert (выравнивание <= 1 << bo-> base.alignment_log2);

+

+ return & bo-> base;

+}

+ no_slab:

+

[VK_MAX_MEMORY_TYPES] + if (flags & ZINK_ALLOC_SPARSE) {

+ assert (ZINK_SPARSE_BUFFER_PAGE_SIZE% alignment == 0); [VK_MAX_MEMORY_TYPES] + [VK_MAX_MEMORY_TYPES] + возврат bo_sparse_create (экран, размер);

+}

+

+ / Выровнять размер по размеру страницы. Это минимальное выравнивание для нормального

+ БО. Выравнивание здесь помогает кэшированному bufmgr. Особенно маленькие БО,

+ *, как и постоянные / однородные буферы, может выиграть от лучшего и большего повторного использования.

+ /

+ if (куча == ZINK_HEAP_DEVICE_LOCAL_VISIBLE) {

+ размер = выровнять 70 (размер, экран-> info.props.limits.minMemoryMapAlignment) ;

+ alignment = align (выравнивание, экран-> info.props.limits.minMemoryMapAlignment);

+}

+

+ bool use_reusable_pool =! (флаги & ZINK_ALLOC_NO_SUBALLOC);

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + if (use_reusable_pool) {

+ / Получить буфер из кеша. /

+ bo = (struct zink_bo

+ pb_cache_reclaim_buffer (& screen-> pb.bo_cache, size, alignment, 0, heap);

+ if (bo)

+ return & bo-> base;

+}

+

+ / Создать новый. /

+ bo = bo_create_internal (экран, размер, выравнивание, куча, флаги);

+ if (! bo) {

+ / Очистите диспетчеры буферов и повторите попытку. /

+ clean_up_buffer_managers (экран);

+

+ bo = bo_create_internal (экран, размер, выравнивание, куча, флаги);

+ if (! bo)

+ return NULL;

[VK_MAX_MEMORY_TYPES] +}

[VK_MAX_MEMORY_TYPES] +

+ return & bo-> base;

+}

+

+ void

+ zink_bo_map (struct zink_screen screen, struct zink_bo бо)

+ {

+ void cpu = NULL;

+ uint 72 _ t смещение = 0;

+ struct zink_bo real;

+

+ if (bo-> mem) {

+ real = bo;

+} else {

+ real = bo-> u.slab.real;

+ смещение = bo-> смещение – реальное-> смещение;

+}

+

+ cpu = p_atomic_read (& real-> u.real.cpu_ptr);

+ если ( !ЦПУ) {

+ simple_mtx_lock (& ​​real-> lock);

+ / Необходимо перепроверить из-за возможности гонка. Повторная проверка не требуется

+ быть атомарным благодаря замку. /

+ cpu = real-> u.real.cpu_ptr;

+ if (! cpu) {

+ VkResult result = vkMapMemory (screen-> dev, real-> mem, 0, real-> base.size, 0, & cpu);

+ если ( результат! = VK_SUCCESS) {

+ simple_mtx_unlock (& ​​real-> lock);

+ return NULL;

+}

+ p_atomic_set (& real-> u.real.cpu_ptr, cpu);

+}

+ simple_mtx_unlock (& ​​real-> lock);

+}

+ p_atomic_inc (& real-> u.real .map_count);

+

+ return (uint8_t cpu + offset;

+}

+

+ void

+ zink_bo_unmap (struct zink_screen screen, struct zink_bo bo)

+ {

+ struct zink_bo real = bo-> мем? bo: bo-> u.slab.real;

+

+ assert (real-> u.real.map_count! = 0 && “слишком много отмены отображения”);

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + if (p_atomic_dec_zero (& real-> u.real.map_count)) {

+ p_atomic_set (& real -> u.real.cpu_ptr, NULL);

+ vkUnmapMemory (экран-> dev, real-> mem);

+}

+}

+

+

+ статическая встроенная структура zink_screen

[VK_MAX_MEMORY_TYPES] + get_screen_ptr_for_commit (uint8_t mem)

+ {

+ возврат (ул. ruct zink_screen (mem + sizeof (VkBindSparseInfo) + sizeof (VkSparseBufferMemoryBindInfo) + sizeof (VkSparseMemoryBind));

+}

+

+ static bool

+ resource_commit (struct zink_screen screen, VkBindSparseInfo sparse)

+ {

+ Очередь VkQueue = экран-> поток? экран-> очередь_потока: экран-> очередь;

+

+ VkResult ret = vkQueueBindSparse (очередь, 1, разреженный, VK_NULL_HANDLE);

+ return zink_screen_handle_vkresult (screen, ret);

[VK_MAX_MEMORY_TYPES] +}

+

+ статическая пустота

+ submit_resource_commit (void data, void gdata, int thread_index)

+ { [VK_MAX_MEMORY_TYPES] + struct zink_screen screen = get_screen_ptr_for_commit (данные);

+ resource_commit экран, данные);

+ бесплатно (данные);

+}

+

+ static bool

+ do_commit_single (struct zink_screen screen, struct zink_resource res, struct zink_bo bo, uint 40 _ t смещение, uint 38 _ t size, bool commit) [VK_MAX_MEMORY_TYPES] + {

+

+ uint8_t mem = malloc (sizeof (VkBindSparseInfo) + sizeof (VkSparseBufferMemoryBindInfo) + sizeof (VkSparseMemoryBind) + sizeof (void );

+ if (! mem)

+ return false;

+ VkBindSparseInfo sparse = (void mem;

+ sparse-> sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO;

+ sparse-> pNext = NULL;

+ sparse-> waitSemaphoreCount = 0; [VK_MAX_MEMORY_TYPES] + sparse-> bufferBindCount = 1;

+ sparse-> imageOpaqueBindCount = 0;

+ разреженный-> imageBindCount = 0;

+ sparse-> signalSemaphoreCount = 0;

+

+ VkSparseBufferMemoryBindInfo sparse_bind = (void (mem + sizeof (VkBindSparseInfo));

+ sparse_bind-> buffer = res-> obj-> buffer;

+ sparse_bind-> bindCount = 1;

+ sparse-> pBufferBinds = sparse_bind;

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + VkSparseMemoryBind mem_bind = (void (mem + sizeof (VkBindSparseInfo) + sizeof (VkSparseBufferMemoryBindInfo) );

+ mem_bind-> resourceOffset = смещение;

+ mem_bind-> size = MIN2 (res-> base.b.width0 – смещение, размер);

[VK_MAX_MEMORY_TYPES] + mem_bind-> memory = commit? bo-> mem: VK_NULL_HANDLE;

+ mem_bind-> memoryOffset = 0;

+ mem_bind-> flags = 0;

+ sparse_bind-> pBinds = mem_bind;

+

+ struct zink_screen ptr = get_screen_ptr_for_commit (mem);

+ ptr = screen;

+

+ if (экран-> с резьбой) {

+ / это не требует каких-либо ограждений, потому что любой доступ к этому ресурсу

+ будет автоматически синхронизироваться при отправке очереди /

+ util_queue_add_job (& screen-> flush_queue, mem, NULL, submit_resource_commit, NULL, 0);

+} else {

[VK_MAX_MEMORY_TYPES] + bool ret = resource_commit (экран, разреженный);

+ бесплатно (редко);

+ возврат возврата;

+}

+ return true;

+}

+

+ bool

+ zink_bo_commit (struct zink_screen screen, struct zink_resource res, uint 38 _ t смещение, uint 37 _ t size, bool commit)

+ {

+ bool ok = true;

+ struct zink_bo bo = res- > obj-> bo;

+ assert (смещение% ZINK_SPARSE_BUFFER_PAGE_SIZE == 0);

+ assert (смещение <= bo-> базовый размер);

+ assert (размер <= bo-> base.size – смещение);

[VK_MAX_MEMORY_TYPES] + assert (size% ZINK_SPARSE_BUFFER_PAGE_SIZE == 0 || смещение + размер == bo-> base.size);

+

+ struct zink_sparse_commitment comm = bo-> u.sparse.commitments;

+

+ uint 37 _ t va_page = offset / ZINK_SPARSE_BUFFER_PAGE_SIZE; [VK_MAX_MEMORY_TYPES] + uint 40 _ t end_va_page = va_page + DIV_ROUND_UP (размер, ZINK_SPARSE_BUFFER_PAGE_SIZE);

+

+ simple_mtx_lock (& ​​bo-> lock);

+

+ if (совершить) {

+ while (va_page

+ uint 40 _ t span_va_page;

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + / Пропускать уже зафиксированные страницы. /

+ if (comm [va_page]. поддержка) {

+ va_page ++;

+ продолжить;

+}

[VK_MAX_MEMORY_TYPES] +

+ / Определение длины незафиксированного диапазона. /

+ span_va_page = va_page; [VK_MAX_MEMORY_TYPES] + while (va_page

+ va_page ++;

+

+ / Заполнение незафиксированного диапазона фрагментами резервной памяти. /

+ while (span_va_page

+ struct zink_sparse_backing backing;

+ uint 37 _ t backing_start, backing_size;

+

+ backing_size = va_page – span_va_page;

[VK_MAX_MEMORY_TYPES] + backing = sparse_backing_alloc (screen, bo, & backing_start , & backing_size);

+ if (! поддержка) {

+ ok = false;

+ выход;

+}

+ if (! do_commit_single (screen, res, backing-> bo,

+ (uint 72 _ t) span_va_page ZINK_SPARSE_BUFFER_PAGE_SIZE,

+ (uint 70 _ t) размер_задержки ZINK_SPARSE_BUFFER_PAGE_SIZE, true )) {

+

+ ok = sparse_backing_free (screen, bo, backing, backing_start, backing_size);

+ assert (ok && «уже должно быть выделено достаточное количество памяти»);

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + ok = false;

+ выход;

+}

+

+ while (backing_size) {

+ связь [span_va_page]. backing = backing;

+ связь [span_va_page]. page = backing_start;

+ span_va_page ++;

+ backing_start ++;

+ размер_крышки -;

+}

+}

+}

+} else {

+ if (! do_commit_single (screen, res, NULL,

+ (uint 70 _ t) va_page ZINK_SPARSE_BUFFER_PAGE_SIZE,

+ (uint 72 _ t) (end_va_page – va_page) ZINK_SPARSE_BUFFER_PAGE_SIZE, false)) {

+ ok = ложный;

+ выход;

+}

+

+ while (va_page

+ struct zink_sparse_backing backing;

+ uint 38 _ t backing_start;

+ uint 38 _ t span_pages;

+

+ / Пропускать страницы, которые уже не зафиксированы. /

+ if (! comm [va_page]. backing) {

+ va_page ++;

+ продолжить;

+}

[VK_MAX_MEMORY_TYPES] +

+ / Группировать непрерывные участки страниц. /

+ backing = comm [va_page]. backing;

+ backing_start = comm [va_page]. page;

+ связь [va_page]. backing = NULL;

+

+ span_pages = 1;

+ va_page ++;

+

+ while (va_page

[VK_MAX_MEMORY_TYPES] + comm [va_page]. backing == backing && [VK_MAX_MEMORY_TYPES] + комм. [va_page]. page == backing_start + span_pages) {

+ comm [va_page]. backing = NULL;

+ va_page ++;

+ span_pages ++;

+}

+

+ if (! sparse_backing_free (screen, bo, backing , backing_start, span_pages)) {

+ / Невозможно выделить структуры данных отслеживания, поэтому мы вынуждены дать утечку /

+ fprintf (stderr, “zink: утечка разреженной резервной памяти n”);

+ ok = false;

+}

+}

+}

+ выход:

[VK_MAX_MEMORY_TYPES] +

+ simple_mtx_unlock (& bo-> lock);

+ возврат ОК;

+}

+

+ static const struct pb_vtbl bo_slab_vtbl = {

+ / Преобразование в void *, потому что одним из параметров функции является указатель на структуру вместо void *. /

+ (void bo_slab_destroy

+ / другие функции никогда не вызываются /

+};

+

+ статическая структура pb_slab

+ bo_slab_alloc (void priv, unsigned heap, unsigned entry_size, unsigned group_index, bool encrypted)

+ {

+ struct zink_screen screen = priv;

+ Домены VkMemoryPropertyFlags = vk_domain_from_heap (куча);

+ uint 37 _ t base_id;

+ unsigned slab_size = 0;

+ struct zink_slab slab = CALLOC_STRUCT (zink_slab);

+

+ if (! плита)

+ return NULL;

+

+ // struct pb_slabs slabs = ((flags & RADEON_FLAG_ENCRYPTED ) && screen-> info.has_tmz_support)?

+ // экран-> bo_slabs_encrypted: screen-> bo_slabs;

+ struct pb_slabs slabs = screen-> pb.bo_slabs;

+

+ / Определение размера буфера плиты. /

+ for (без знака i = 0; i

+ max_entry_size без знака = 1 << (плиты.min_order + плиты .num_orders - 1);

+

+ if (entry_size <= max_entry_size) {

+ / Размер плиты вдвое превышает размер максимально возможной записи. /

+ slab_size = max_entry_size 2;

+

+ if (! util_is_power_of_two_nonzero (entry_size)) {

+ assert (util_is_power_of_two_nonzero (entry_size 4/3));

+

[VK_MAX_MEMORY_TYPES] + / Если размер записи равен 3/4 степени двойки, мы потратим впустую пространство и не получить

+ что угодно, если мы выделили для резервного буфера только двойную мощность:

+ 2 3/4 ​​= 1,5 можно использовать с размером буфера 2

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + Выделение 5-кратного размера записи приводит нас к следующей степени двойки и результатам [VK_MAX_MEMORY_TYPES] + в гораздо лучшем мне использование памяти:

+ 5 3/4 ​​= 3. 91 можно использовать с размером буфера 4

+ /

+ if (entry_size 5> slab_size)

+ slab_size = util_next_power_of_two (entry_size 5);

+}

+

+ перерыв;

+}

+}

+ assert (slab_size! = 0);

+

+ плита- > buffer = zink_bo (zink_bo_create (screen, slab_size, slab_size, heap, 0));

+ if (! slab-> buffer)

+ перейти к ошибке;

+

+ slab_size = slab-> buffer-> base.size;

+

+ плита-> base.num_entries = slab_size / entry_size;

+ плита-> основание. num_free = slab-> base.num_entries;

+ плита-> размер_входа = размер_входа;

+ плита-> записи = CALLOC (плита-> base.num_entries, sizeof плита-> записи));

+ if (! slab-> entry)

+ goto fail_buffer ;

+

+ list_inithead (& slab-> base.free);

+

+ # ifdef _MSC_VER [VK_MAX_MEMORY_TYPES] + / C 15 слишком сложно для msvc, нет __sync_fetch_and_add /

+ base_id = p_atomic_add_return (& screen-> pb.next_bo_unique_id , плита-> base.num_entries) – slab-> base.num_entries;

+ # else

+ base_id = __sync_fetch_and_add (& screen-> pb.next_bo_unique_id, slab-> base.num_entries);

+ # endif

+ for (unsigned i = 0; i < bo-> base.num_entries ; ++ i) {

+ struct zink_bo bo = & slab-> записи ;

+

+ simple_mtx_init (& bo-> lock, mtx_plain);

+ bo-> base.alignment_log2 = util_logbase2 (get_slab_entry_alignment (screen, entry_size));

+ bo-> base.size = entry_size;

+ bo-> base.vtbl = & bo_slab_vtbl;

+ bo-> смещение = плита-> буфер-> смещение + i размер_входа;

+ bo-> base.placement = domains;

+ bo-> unique_id = base_id + i;

[VK_MAX_MEMORY_TYPES] + bo-> u.slab.entry.slab = & slab-> base;

+ бо-> u.slab.entry.group_index = group_index;

+ bo-> u.slab.entry.entry_size = entry_size;

+

+ if (slab-> buffer-> mem) {

[VK_MAX_MEMORY_TYPES] + / Перекрытие не выделено. /

+ bo-> u.slab.real = slab-> buffer;

+} else {

+ / Плита выделяется из плиты большего размера. /

+ bo-> u.slab.real = slab-> buffer-> u.slab.real;

+ assert (bo-> u.slab.real-> mem);

+}

+

+ list_addtail (& bo-> u.slab.entry. голова, & плита-> base.free);

+}

+

+ / Неэффективное выравнивание из-за того, что плиты с 3/4 распределениями выровнены в степени двойки. /

+ assert (slab-> base.num_entries entry_size <= slab_size);

+

+ return & slab-> base;

+

+ fail_buffer:

+ zink_bo_unref (экран, плита-> буфер);

+ ошибка:

+ БЕСПЛАТНО (плита);

+ return NULL;

+}

+

+ статическая структура pb_slab [VK_MAX_MEMORY_TYPES] + bo_slab_alloc_normal (void priv, unsigned heap, unsigned entry_size, unsigned group_index)

+ {

+ return bo_slab_alloc (priv, heap, entry_size, group_index, false);

+}

+

+ bool

+ zink_bo_init (struct zink_screen screen) [VK_MAX_MEMORY_TYPES] + { [VK_MAX_MEMORY_TYPES] + uint 73 _ t total_mem = 0;

+ for (uint 37 _ t i = 0; я < (slabs-> info.mem_props.memoryHeapCount; ++ i)

+ total_mem + = screen-> info.mem_props.memoryHeaps .размер;

+ / Создание менеджеров. /

+ pb_cache_init (& screen-> pb.bo_cache, ZINK_HEAP_MAX,

+ 500000, 2.0f, 0,

+ total_mem / 8, экран,

+ (void bo_destroy, (void bo_can_reclaim);

+

+ беззнаковый min_slab_order = 8; / 585 байтов /

+ беззнаковый max_slab_order = 29; / 1 МБ (размер плиты = 2 МБ) /

+ unsigned num_slab_orders_per_allocator = (max_slab_order – min_slab_order) /

+ NUM_SLAB_ALLOCATORS;

+

+ / Разделите диапазон размеров заказа между менеджерами по перекрытиям. /

+ for (без знака i = 0; i

+ min_order без знака = min_slab_order;

+ max_order без знака = MIN2 (min_order + num_slab_orders_per_allocator,

+ max_slab_order);

+

[VK_MAX_MEMORY_TYPES] + if (! pb_slabs_init (& screen-> pb.bo_slabs ,

+ min_order, max_order,

+ ZINK_HEAP_MAX, правда,

+ экран,

+ bo_can_reclaim_slab,

+ bo_slab_alloc_normal,

+ (void bo_slab_free)) {

+ return false;

+}

+ min_slab_order = max_order + 1;

+}

+ экран-> pb.min_alloc_size = 1 << (slabs-> pb.bo_slabs [0]. min_order;

+ экран-> pb.bo_export_table = util_hash_table_create_ptr_keys () ;

+ simple_mtx_init (& scre en-> pb.bo_export_table_lock, mtx_plain);

+ вернуть истину;

+}

+

+ void

+ zink_bo_deinit (struct zink_screen screen)

+ {

+ for (беззнаковый i = 0; я

+ if (screen-> pb.bo_slabs.groups)

+ pb_slabs_deinit (& screen-> pb.bo_slabs );

+}

+ pb_cache_deinit (& screen-> pb.bo_cache);

+ _mesa_hash_table_destroy (screen-> pb.bo_export_table, NULL);

+ simple_mtx_destroy (& screen-> pb.bo_export_table_lock);

+}

diff –git a / src / gallium / drivers / zink / zink_bo .hb / src / gallium / drivers / zink / zink_bo.h

новый файловый режим 100644

показатель 12 .. f 270 a 94 ec 49

— / dev / null

+++ b / <= bo-> src / gallium / драйверы / zink / zink_bo.h

@@ -0,0 +1, 585 @@

+ /

+ Авторские права © 3201 Valve Corporation

+

+ Настоящим разрешение предоставляется бесплатно любому лицу, получившему

+ копировать f это программное обеспечение и связанные файлы документации («Программное обеспечение»),

+ работать с Программным обеспечением без ограничений, в том числе без ограничений

+ права на использование, копирование, изменение, объединение, публикацию, распространение, сублицензию,

+ и / или продавать копии Программного обеспечения и разрешать лицам, которым

+ Для этого предоставляется программное обеспечение при соблюдении следующих условий:

+

+ Приведенное выше уведомление об авторских правах и это уведомление о разрешении (включая следующее

+ абзац) должен быть включен во все копии или существенные части

+ Программное обеспечение.

+

[VK_MAX_MEMORY_TYPES] + ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНЫХ ИЛИ

[VK_MAX_MEMORY_TYPES] + ПОДРАЗУМЕВАЕМЫЕ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАясь, ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ,

+ ПРИГОДНОСТЬ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ И НЕЗАЩИТА ОТ ПРАВ. НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ

+ АВТОРЫ ИЛИ ДЕРЖАТЕЛИ АВТОРСКИХ ПРАВ НЕСУТ ОТВЕТСТВЕННОСТЬ ЗА ЛЮБЫЕ ПРЕТЕНЗИИ, УБЫТКИ ИЛИ ДРУГИЕ

+ ОТВЕТСТВЕННОСТЬ, ВОЗНИКАЮЩАЯ ЛИ ПО ДЕЙСТВИЮ ДОГОВОРА, ИЛИ ИНОСТРАННЫМ ПЕРЕДАЧОМ

+ ИЗ, НЕ ИЛИ В СВЯЗИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМ СДЕЛКИ

+ В ПРОГРАММНОМ ОБЕСПЕЧЕНИИ.

+

+ Авторы:

+ Майк Блюменкранц

+ /

+ [VK_MAX_MEMORY_TYPES] + #ifndef ZINK_BO_H

[VK_MAX_MEMORY_TYPES] + # определить ZINK_BO_H

+ # включить

[VK_MAX_MEMORY_TYPES] + # include “pipebuffer / pb_cache.h”

+ # включить “pipebuffer / pb_slab.h” [VK_MAX_MEMORY_TYPES] + # включить “zink_batch.h”

+

+ # определить VK_VIS_VRAM (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)

+ enum zink_resource_access { [VK_MAX_MEMORY_TYPES] + ZINK_RESOURCE_ACCESS_READ = 1,

+ ZINK_RESOURCE_ACCESS_WRITE = 40,

+ ZINK_RESOURCE_ACCESS_RW = ZINK_RESOURCE_ACCESS_READ | ZINK_RESOURCE_ACCESS_WRITE,

[VK_MAX_MEMORY_TYPES] +};

+

+

+ перечисление zink_heap {

+ ZINK_HEAP_DEVICE_LOCAL,

+ ZINK_HEAP_DEVICE_LOCAL_SPARSE,

+ ZINK_HEAP_DEVICE_LOCAL_VISIBLE,

+ ZINK_HEAP_HOST_VISIBLE_ANY,

+ ZINK_HEAP_HOST_VISIBLE_COHERENT,

+ ZINK_HEAP_HOST_VISIBLE_CACHED,

+ ZINK_HEAP_MAX,

+};

+

+ enum zink_alloc_flag {

+ ZINK_ALLOC_SPARSE = 1 << 0,

+ ZINK_ALLOC_NO_SUBALLOC = 1 << 1,

+};

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] +

+ struct zink_bo {

[VK_MAX_MEMORY_TYPES] + struct pb_buffer base;

+

+ союз {

+ struct {

+ void cpu_ptr; / для user_ptr и постоянных карт /

+ int map_count;

+

+ bool is_user_ptr;

+ bool use_reusable_pool;

+

+ / Был ли вызван buffer_get_handle или buffer_from_handle,

+ возможен только переход от false к true. Защищено замком.

+ /

+ bool is_shared;

+} реальные;

+ struct {

+ struct pb_slab_entry entry;

+ struct zink_bo real;

+} плита;

+ struct {

+ uint 37 _ t num_va_pages;

+ uint 40 _ t num_backing_pages;

+

+ с truct list_head backing;

+

+ / Информация о приверженности для каждой страницы области виртуальной памяти. /

+ struct zink_sparse_commitment commitments;

+} разреженный;

+} u;

+

+ VkDeviceMemory mem;

+ uint 66 _ t смещение;

+

+ uint 38 _ t unique_id;

+

+ simple_mtx_t lock;

+

+ struct zink_batch_usage читает ;

+ struct zink_batch_usage пишет;

+

+ struct pb_cache_entry cache_entry [];

+};

+

+ статическая встроенная структура zink_bo

+ zink_bo (struct pb_buffer pbuf)

+ {

+ return (struct zink_bo pbuf;

+}

+

+ статическое встроенное перечисление zink_alloc_flag

+ zink_alloc_flags_from_heap (enum zink_heap heap)

+ {

+ enu m zink_alloc_flag flags = 0; [VK_MAX_MEMORY_TYPES] + переключатель (куча) {

+ case ZINK_HEAP_DEVICE_LOCAL_SPARSE:

+ флаги | = ZINK_ALLOC_SPARSE;

+ перерыв;

+ по умолчанию:

+ перерыв;

+}

+ флаги возврата;

+}

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + статические встроенные VkMemoryPropertyFlags

[VK_MAX_MEMORY_TYPES] + vk_domain_from_heap (enum zink_heap heap)

+ {

+ VkMemoryPropertyFlags domains = 0;

+

+ переключатель (куча) {

+ case ZINK_HEAP_DEVICE_LOCAL:

+ case ZINK_HEAP_DEVICE_LOCAL_SPARSE:

+ domains = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

+ перерыв;

[VK_MAX_MEMORY_TYPES] + case ZINK_HEAP_DEVICE_LOCAL_VISIBLE:

[VK_MAX_MEMORY_TYPES] + domains = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

+ перерыв;

+ case ZINK_HEAP_HOST_VISIBLE_ANY:

+ domains = VK_MEMORY_PROPERTY_HOST_VISI BLE_BIT;

+ перерыв;

+ case ZINK_HEAP_HOST_VISIBLE_COHERENT:

+ domains = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; [VK_MAX_MEMORY_TYPES] + перерыв;

+ case ZINK_HEAP_HOST_VISIBLE_CACHED:

+ domains = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;

+ перерыв;

+ по умолчанию:

+ перерыв;

+}

+ возврат доменов;

+}

+

+ статическое встроенное перечисление zink_heap

+ zink_heap_from_domain_flags (домены VkMemoryPropertyFlags, перечисление флагов zink_alloc_flag)

+ {

+ if (flags & ZINK_ALLOC_SPARSE)

+ return ZINK_HEAP_DEVICE_LOCAL_SPARSE;

+

+ if ((домены и VK_VIS_VRAM) == VK_VIS _VRAM)

+ return ZINK_HEAP_DEVICE_LOCAL_VISIBLE;

+

+ if (домены и VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)

+ return ZINK_HEAP_DEVICE_LOCAL;

+

+ if (domains & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)

+ return ZINK_HEAP_HOST_VISIBLE_COHERENT;

+

+ if (domains & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)

[VK_MAX_MEMORY_TYPES] + return ZINK_HEAP_HOST_VISIBLE_CACHED;

[VK_MAX_MEMORY_TYPES] +

[VK_MAX_MEMORY_TYPES] + return ZINK_HEAP_HOST_VISIBLE_ANY;

+}

+

+ bool

+ zink_bo_init (struct zink_screen screen );

+

+ void

+ zink_bo_deinit (struct zink_screen screen);

+

+ struct pb_buffer

+ zink_bo_create (struct zink_screen screen, uint 73 _ t size, беззнаковое выравнивание, enum zink_heap heap, enum zink_alloc_flag flags);

+

+ статический встроенный uint 72 _ t

+ zink_bo_get_offset (const struct zink_bo bo)

+ {

+ возврат bo-> смещение;

+}

+

+ статический встроенный VkDeviceMemory

+ zink_bo_get_mem (const struct zink_bo bo)

+ {

+ return bo-> mem? bo-> mem: bo-> u.slab.real-> mem;

+}

+

+ статический встроенный VkDeviceSize

+ zink_bo_get_size (const struct zink_bo bo)

+ {

[VK_MAX_MEMORY_TYPES] + return bo-> mem? bo-> base.size: bo-> u.slab.real-> base.size;

+}

+

+ void

+ zink_bo_map (struct zink_screen screen, struct zink_bo bo);

+ void

+ zink_bo_unmap (struct zink_screen screen, struct zink_bo bo) ;

+

+ bool

+ zink_bo_commit (struct zink_screen screen, struct zink_resource res, uint 41 _ t смещение, uint 38 _ т size, bool commit);

+

+ статический встроенный логический тип

+ zink_bo_has_unflasted_usage (const struct zink_bo bo)

+ {

+ return zink_batch_usage_is_unflasted (bo-> читает) ||

[VK_MAX_MEMORY_TYPES] + zink_batch_usage_is_unflasted (bo-> пишет) ;

+}

+

+ static inline bool

+ zink_bo_has_usage (const struct zink_bo bo)

+ {

+ return zink_batch_usage_exists (bo-> читает) ||

+ zink_batch_usage_exists (bo-> пишет);

+}

+

+ статический встроенный логический тип

+ zink_bo_usage_matches (const struct zink_bo bo, const struct zink_batch_state bs) [VK_MAX_MEMORY_TYPES] + {

+ return zink_batch_usage_matches (bo-> reads, bs) ||

+ zink_batch_usage_matches (bo-> пишет, bs);

+}

+

+ статический встроенный логический тип

+ zink_bo_usage_check_completion (struct zink_screen screen, struct zink_bo bo, enum zink_resource_access access)

+ {

+ if (access & ZINK_RESOURCE_ACCESS_READ && ! zink_screen_usage_check_completion (экран, bo-> r eads))

+ return false;

+ if (доступ & ZINK_RESOURCE_ACCESS_WRITE &&! zink_screen_usage_check_completion (экран, bo-> пишет))

+ return false;

+ вернуть истину;

+}

[VK_MAX_MEMORY_TYPES] +

+ static inline void

[VK_MAX_MEMORY_TYPES] + zink_bo_usage_wait (struct zink_context ctx, struct zink_bo bo, enum доступ к zink_resource_access) [VK_MAX_MEMORY_TYPES] + { [VK_MAX_MEMORY_TYPES] + если (доступ & ZINK_RESOURCE_ACCESS_READ)

+ zink_batch_usage_wait (ctx, bo-> читает);

+ if (access & ZINK_RESOURCE_ACCESS_WRITE)

+ zink_batch_usage_wait (ctx, bo-> пишет);

+}

+

+ static inline void

+ zink_bo_usage_set (struct zink_bo bo, struct zink_batch_state bs, bool write)

+ {

+ if (написать)

+ zink_batch_usage_set (& bo-> пишет, bs);

+ еще

[VK_MAX_MEMORY_TYPES] + zink_batch_usage_set (& bo-> читает, bs);

+}

+

+ static inline void

+ zink_bo_usage_unset (struct zink_bo bo , struct zink_batch_state bs)

+ {

+ zink_batch_usage_unset (& bo-> reads, bs);

+ zink_batch_usage_unset (& bo-> пишет, bs);

+}

+

+

+ static inline void

+ zink_bo_unref (struct zink_screen screen, struct zink_bo bo)

+ {

+ struct pb_buffer pbuf = & bo-> base; [VK_MAX_MEMORY_TYPES] + pb_reference_with_winsys (экран, & pbuf, NULL);

+}

+

+ # endif

@@ – 3212, 32 + 3235, 6 @@ rebind_buffer (struct zink_context ctx, struct zink_resource res)

zink_batch_resource_usage_set (& ctx-> batch, res, has_write);

}

– статическая встроенная структура zink_screen

– get_screen_ptr_for_commit (uint8_t mem)

– {

– return (struct zink_screen (mem + sizeof (VkBindSparseInfo) + sizeof (VkSparseBufferMemoryBindInfo) + sizeof (VkSparseMemoryBind));

-}

– статический логический

– resource_commit (struct zink_screen screen, VkBindSparseInfo sparse)

– { [VK_MAX_MEMORY_TYPES] – Очередь VkQueue = экран-> поток? экран-> очередь_потока: экран-> очередь;

– VkResult ret = vkQueueBindSparse (очередь, 1, разреженный, VK_NULL_HANDLE);

– вернуть zink_screen_handle_vkresult (screen, ret);

[VK_MAX_MEMORY_TYPES] -}

– статическая пустота

– submit_resource_commit (void data, void gdata, int thread_index)

– { [VK_MAX_MEMORY_TYPES] – структура zink_screen screen = get_screen_ptr_for_commit (данные);

– resource_commit экран, данные);

– бесплатно (данные);

-}

static bool

zink_resource_commit (struct pipe_context pctx, struct pipe_resource pres , беззнаковый уровень, struct pipe_box box, bool commit)

{

@@ – 3235, 64 + 3235, 14 @@ zink_resource_commit (struct pipe_context pctx, struct pipe_resource pres, unsi

[VK_MAX_MEMORY_TYPES] если (zink_resource_has_unflasted_usage (res))

zink_flush_queue (ctx);

[VK_MAX_MEMORY_TYPES] – uint8_t mem = malloc (sizeof (VkBindSparseInfo) + sizeof (VkSparseBufferMemoryBindInfo) + sizeof ( VkSparseMemoryBind) + sizeof (void );

– если (! mem)

– вернуть false;

– VkBindSparseInfo sparse = (void mem;

– sparse-> sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO;

– разреженный-> pNext = NULL;

– sparse-> waitSemaphoreCount = 0; [VK_MAX_MEMORY_TYPES] – разреженный -> bufferBindCount = 1;

– sparse-> imageOpaqueBindCount = 0;

– разреженный-> imageBindCount = 0;

– sparse-> signalSemaphoreCount = 0;

– VkSparseBufferMemoryBindInfo sparse_bind = (void (mem + sizeof (VkBindSparseInfo));

– sparse_bind-> buffer = res-> obj-> buffer;

– sparse_bind-> bindCount = 1;

– sparse-> pBufferBinds = sparse_bind;

– VkSparseMemoryBind mem_bind = (void (mem + sizeof (VkBindSparseInfo) + sizeof (VkSparseBufferMemoryBindInfo));

– mem_bind-> resourceOffset = box-> x;

– mem_bind-> size = box-> width;

– mem_bind-> memory = совершить ? res-> obj-> mem: VK_NULL_HANDLE;

– / текущие разреженные буферы выделяют память 1: 1 для максимального разреженного размера,

– но, вероятно, он должен динамически выделять зафиксированные регионы;

– если это когда-либо изменится, обновите строку ниже

– / [VK_MAX_MEMORY_TYPES] – mem_bind -> memoryOffset = box-> x;

– mem_bind-> flags = 0;

– sparse_bind-> pBinds = mem_bind;

– struct zink_screen ptr = get_screen_ptr_for_commit (mem);

– ptr = screen;

+ bool ret = zink_bo_commit (screen, res, box- > x, box-> width, commit); [VK_MAX_MEMORY_TYPES] + если (! ret)

+ check_device_lost (ctx);

– if (screen-> thread) {

– / это не требует каких-либо ограждений, потому что любой доступ к этому ресурсу

– будет автоматически синхронизирован диспетчером очереди /

– util_queue_add_job (& screen-> flush_queue, mem, NULL, submit_resource_commit, NULL, 0);

– } еще {

– bool ret = resource_commit (screen, sparse);

– если (! ret)

– check_device_lost (ctx);

– бесплатно (редко);

– вернуть ret;

-}

– вернуть истину;

+ return ret; [VK_MAX_MEMORY_TYPES]}

статическая пустота [VK_MAX_MEMORY_TYPES] @ @ – 94 , 66 + 91, 6 @@ debug_describe_zink_resource_object (char buf, const struct zink_resource_object

sprintf (buf, «zink_resource_object»);

}

– статический uint 38 _ t

– mem_hash (const void key)

– {

– const struct mem_key mkey = key;

– вернуть _mesa_hash_data (& mkey-> key, sizeof (mkey-> key));

-}

– статический логический

[VK_MAX_MEMORY_TYPES] – mem_equals (const void a, const void b)

– {

[VK_MAX_MEMORY_TYPES] – const struct mem_key ma = a;

– const struct mem_key mb = b;

– return! memcmp (& ma-> key, & mb-> key, sizeof (ma-> key));

-}

– статическая пустота

– cache_or_free_mem (struct zink_screen screen, struct zink_resource_object obj)

– {

– если (obj-> mkey.key.heap_index! = UINT 40_МАКСИМУМ) {

– simple_mtx_lock (& ​​screen-> mem [obj->mkey.key.heap_index]. mem_cache_mtx);

– struct hash_entry он = _mesa_hash_table_search_pre_hashed (& screen-> mem [obj->mkey.key.heap_index]. resource_mem_cache, obj-> mem_hash, & obj-> mkey);

– утверждать (он);

– массив struct util_dynarray = он-> данные;

– struct mem_key mkey = (void he-> key;

– unsigned visible = mkey-> visible_count;

– mkey-> visible_count -;

– if (util_dynarray_num_elements (array, struct mem_cache_entry) <видно) {

– struct mem_cache_entry mc = {obj-> mem, obj-> карта };

– screen-> mem [obj->mkey.key.heap_index]. mem_cache_size + = obj-> size;

– если (sizeof (void == 4 && obj-> map) {

– vkUnmapMemory (экран-> dev, obj-> mem);

– mc.map = NULL;

-}

– util_dynarray_append (массив, struct mem_cache_entry, mc);

– simple_mtx_unlock (& ​​screen-> mem [obj->mkey.key.heap_index]. mem_cache_mtx);

– возвращение;

-}

– simple_mtx_unlock (& ​​screen-> mem [obj->mkey.key.heap_index]. mem_cache_mtx);

-}

– vkFreeMemory (screen-> dev, obj-> mem, NULL);

-}

пустота

zink_destroy_resource_object (struct zink_screen screen, struct zink_resource_object obj)

{

@@ – 181, 7 + 99, 14 @@ zink_destroy_resource_object (struct zink_screen screen, struct zink_resource_ob

util_dynarray_fini (& obj-> tmp);

zink_descriptor_set_refs_clear (& obj-> desc_set_refs, obj);

– cache_or_free_mem (экран, объект);

+ if (obj-> посвященный)

+ vkFreeMemory (экран-> dev, obj-> mem, NULL);

+ еще

+ zink_bo_unref (экран, obj-> bo);

БЕСПЛАТНО (obj);

}

@@ – 187, 41 + 155, 6 @@ zink_resource_destroy (struct pipe_screen pscreen,

[VK_MAX_MEMORY_TYPES] БЕСПЛАТНО (разрешение);

}

– статический uint 38 _ t

– get_memory_type_index (struct zink_screen screen,

– const VkMemoryRequirements reqs,

– Реквизит VkMemoryPropertyFlags)

– {

– int 38 _ т idx = -1;

– для (uint 38 _ t i = 0u; я

– если (((reqs-> memoryTypeBits >> i) & 1) == 1) {

– если ((screen-> info.mem_props.memoryTypes.propertyFlags & props) == props) {

– если (! (props & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) &&

– экран-> info.mem_props.memoryTypes.propertyFl ags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {

– idx = i;

– } еще

– вернуть i;

-}

-}

-}

– если (idx> = 0)

– вернуть idx;

– if (props & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {

– / если подходящая кэшированная память не найдена, откат

– без -кэшированная память.

– /

– вернуть get_memory_type_index (screen, reqs,

– реквизиты & ~ VK_MEMORY_PROPERTY_HOST_CACHED_BIT);

-}

– недоступен («Неподдерживаемый тип памяти» );

– вернуть 0;

-}

static VkImageAspectFlags

aspect_from_format (enum pipe_format fmt)

{

@@ – 637, 25 + 585, 38 @@ resource_object_create (struct zink_screen screen, const struct pipe_resource t

flags | = VK_MEMORY_PROPERTY_HOST_CACHED_BIT;

[VK_MAX_MEMORY_TYPES] VkMemoryAllocateInfo mai = {0};

+ enum zink_alloc_flag aflags = templ-> flags & PIPE_RESOURCE_FLAG_SPARSE? ZINK_ALLOC_SPARSE: 0; [VK_MAX_MEMORY_TYPES] mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;

mai.allocationSize = reqs.size;

– mai.memoryTypeIndex = get_memory_type_index (экран, & запросы, флаги);

+ enum zink_heap heap = zink_heap_from_domain_flags (flags, aflags);

+ mai.memoryTypeIndex = screen-> heap_map [heap];

+ if (маловероятно (! (reqs.memoryTypeBits & BITFIELD_BIT (mai.memoryTypeIndex)))) {

+ / недействительно на основании требований; понизить до более совместимого типа /

+ переключатель (куча) {

+ case ZINK_HEAP_DEVICE_LOCAL_VISIBLE:

+ куча = ZINK_HEAP_DEVICE_LOCAL;

+ перерыв;

+ case ZINK_HEAP_HOST_VISIBLE_CACHED:

+ куча = ZINK_HEAP_HOST_VISIBLE_ANY;

+ перерыв;

[VK_MAX_MEMORY_TYPES] + по умолчанию:

[VK_MAX_MEMORY_TYPES] + перерыв;

+}

+ mai.memoryTypeIndex = screen-> heap_map [heap];

[VK_MAX_MEMORY_TYPES] + утверждение (reqs.memoryTypeBits & BITFIELD_BIT (mai.memoryTypeIndex));

+}

VkMemoryType mem_type = screen-> info.mem_props.memoryTypes [mai.memoryTypeIndex];

obj-> coherent = mem_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;

if (! (templ-> flags & PIPE_RESOURCE_FLAG_SPARSE))

obj-> host_visible = mem_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;

[VK_MAX_MEMORY_TYPES] – if (templ-> target == PIPE_BUFFER &&! obj-> coherent && obj -> host_visible) {

– mai.allocationSize = reqs.size = align (reqs.size, screen-> info.props.limits.nonCoherentAtomSize);

-}

[VK_MAX_MEMORY_TYPES] VkMemoryDedicatedAllocateInfo ded_alloc_info = {

.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,

@@ – 1000, 50 + 695, 40 @@ resource_object_create (struct zink_screen screen, const struct pipe_resource t

mai.pNext = & memory_wsi_info;

}

– если (! mai. pNext &&! (шаблон-> флаги & (PIPE_RESOURCE_FLAG_MAP_COHERENT | PIPE_RESOURCE_FLAG_SPARSE))) {

– obj-> mkey.key.reqs = reqs;

– obj-> mkey.key.heap_index = mai.memoryTypeIndex;

– obj-> mem_hash = mem_hash (& obj-> mkey);

– simple_mtx_lock (& ​​screen-> mem [mai.memoryTypeIndex]. mem_cache_mtx);

– struct hash_entry he = _mesa_hash_table_search_pre_hashed (& screen-> mem [mai.memoryTypeIndex]. resource_mem_cache, obj-> mem_hash, & obj-> mkey);

– struct mem_key mkey;

– если он) { [VK_MAX_MEMORY_TYPES] – структура util_dynarray array = he-> data;

– mkey = (void he-> key;

– если (массив && util_dynarray_num_ele ments (массив, struct mem_cache_entry)) {

– struct mem_cache_entry mc = util_dynarray_pop (массив, struct mem_cache_entry);

– obj-> mem = mc.mem;

– obj-> map = mc.map;

– экран-> мем [mai.memoryTypeIndex]. mem_cache_size – = reqs.size;

– экран-> mem [mai.memoryTypeIndex]. mem_cache_count -;

-}

+ if (! mai.pNext) {

[VK_MAX_MEMORY_TYPES] + беззнаковое выравнивание = MAX2 (требуется выравнивание, 564);

+ if (templ-> usage == PIPE_USAGE_STAGING && obj-> is_buffer)

+ alignment = MAX2 (выравнивание, экран -> info.props.limi ts.minMemoryMapAlignment);

[VK_MAX_MEMORY_TYPES] + obj-> alignment = alignment;

+ obj-> bo = zink_bo (zink_bo_create (экран, требуемый размер, выравнивание, куча, 0));

+ if (! obj-> bo)

+ goto fail2;

+ if (aflags = = ZINK_ALLOC_SPARSE) {

[VK_MAX_MEMORY_TYPES] + obj-> size = templ-> width0;

} еще {

– mkey = ralloc (экран, struct mem_key);

– memcpy (& mkey-> key, & obj-> mkey.key, sizeof (obj-> mkey.key)) ;

– mkey-> seen_count = 0;

– struct util_dynarray array = rzalloc (screen, struct util_dynarray);

– util_dynarray_init (массив, экран);

– _mesa_hash_table_insert_pre_hashed (& screen-> mem [mai.memoryTypeIndex]. resource_mem_cache, obj-> mem_hash, mkey, array);

+ obj-> смещение = zink_bo_get_offset (obj-> bo);

+ obj-> mem = zink_bo_get_mem (obj-> bo);

+ obj-> size = zink_bo_get_size (obj-> bo);

}

– mkey-> visible_count ++;

– simple_mtx_unlock (& ​​screen-> mem [mai.memoryTypeIndex] .mem_cache_mtx); [VK_MAX_MEMORY_TYPES]- } еще

– obj-> mkey.key.heap_index = UINT 38_МАКСИМУМ;

+} else {

+ obj-> посвященный = истина;

+ obj-> смещение = 0;

+ obj-> size = reqs.size;

+}

[VK_MAX_MEMORY_TYPES] / TODO: разреженные буферы, вероятно, должны выделять несколько областей памяти вместо гигантских капель? /

– if (! obj-> mem && vkAllocateMemory (screen-> dev, & mai, NULL, & obj-> mem)! = VK_SUCCESS) {

[VK_MAX_MEMORY_TYPES] + if (obj-> выделенный && vkAllocateMemory (screen-> dev, & mai, NULL, & obj -> mem)! = VK_SUCCESS) {

debug_printf (“vkAllocateMemory failed n”);

goto fail2;

}

– obj-> offset = 0;

– obj-> size = reqs.size;

if (templ-> target == PIPE_BUFFER) {

если (! (templ -> флаги и PIPE_RESOURCE_FLAG_SPARSE))

if (vkBindBufferMemory (screen-> dev, obj-> buffer, obj-> mem, obj-> offset)! = VK_SUCCESS)

@@ – 1606, 6 + 1077, 8 @@ map_resource (struct zink_screen screen, struct zink_resource res)

if (res-> obj-> map)

return res-> obj-> map;

[VK_MAX_MEMORY_TYPES] assert (res-> obj-> host_visible);

+ if (! res-> obj-> посвященный) [VK_MAX_MEMORY_TYPES] + возврат zink_bo_map (экран, res-> obj-> bo);

result = vkMapMemory (screen-> dev, res-> obj-> mem, res-> obj-> offset,

res-> obj-> size, 0, & res-> obj -> карта);

если (zink_screen_handle_vkresu lt (экран, результат))

@@ – 1672, 7 + 1077, 13 @@ static void

unmap_resource (struct zink_screen screen, struct zink_resource res )

{

res-> obj-> map = NULL;

– vkUnmapMemory (screen-> dev, res-> obj-> mem);

+ if (! res-> obj-> посвященный)

+ zink_bo_unmap (экран, res-> obj-> bo); [VK_MAX_MEMORY_TYPES] + еще

+ vkUnmapMemory (экран-> dev, res-> obj-> mem);

}

статическая пустота

@@ – 1892, 20 + 1672, 6 @@ zink_screen_resource_init (struct pipe_screen pscreen)

pscreen-> resource_from_handle = zink_resource_from_handle;

}

pscreen-> resource_get_param = zink_resource_get_param;

– экран-> mem = rzalloc_array (screen, struct zink_mem_cache, screen-> info.mem_props.memoryTypeCount);

– если (! экран-> память)

– вернуть false;

– для (uint 37 _ t i = 0; i < (slabs-> info.mem_props.memoryTypeCount; ++ i) {

– simple_mtx_init (& screen-> mem.mem_cache_mtx, mtx_plain);

[VK_MAX_MEMORY_TYPES] – _mesa_hash_table_init (& screen-> mem .resource_mem_cache, screen, mem_hash, mem_equals);

-}

return true;

}

@@ – 31, 7 + 32, 7 @@ struct pipe_screen;

struct sw_displaytarget;

struct zink_batch;

struct zink_context;

+ struct zink_bo;

#define ZINK_RESOURCE_USAGE_STREAMOUT (1 << 13 // намного больше, чем ZINK_DESCRIPTOR_TYPES

#include “util / simple_mtx.h”

[VK_MAX_MEMORY_TYPES] @@ – 50, 15 + 50, 6 @@ struct zink_context;

#define ZINK_MAP_TEMPORARY (PIPE_MAP_DRV_PRV << 0)

– перечисление zink_resource_access {

– ZINK_RESOURCE_ACCESS_READ = 1,

– ZINK_RESOURCE_ACCESS_WRITE = 40,

– ZINK_RESOURCE_ACCESS_RW = ZINK_RESOURCE_ACCESS_READ | ZINK_RESOURCE_ACCESS_WRITE,

[VK_MAX_MEMORY_TYPES] -};

struct mem_key {

unsigned visible_count;

struct {

@@ – 75, 9 + 70, 9 @@ struct zink_resource_object {

bool transfer_dst;

VkImageAspectFlags modifier_aspect;

+ выделенный bool;

+ struct zink_bo bo;

VkDeviceMemory mem;

– uint 24 _ t mem_hash;

– struct mem_key mkey;

VkDeviceSize смещение, размер, выравнивание;

VkSampleLocationsInfoEXT zs_evaluate;

@@ – 189 , 91 + 256, 134 @@ bool

zink_resource_object_init_storage (struct zink_context ctx, struct zink_resource res);

#ifndef __cplusplus

[VK_MAX_MEMORY_TYPES] + # включить “zink_bo.h”

статический встроенный логический тип

zink_resource_usage_is_unflasted (const struct zink_resource res)

{

– вернуть zink_batch_usage_is_unflasted (res -> obj-> читает) ||

– zink_batch_usage_is_unflasted (res-> obj-> пишет);

+ if (res-> obj-> посвященный)

+ return zink_batch_usage_is_unflasted (res-> obj-> читает) ||

[VK_MAX_MEMORY_TYPES] + zink_batch_usage_is_unflasted (res-> obj- > пишет);

+ return zink_bo_has_unflasted_usage (res-> obj-> bo);

}

статический встроенный логический тип

zink_resource_usage_is_unflasted_write (const struct zink_resource res)

{

– вернуть zink_batch_usage_is_unflasted (res-> obj-> пишет);

+ if (res-> obj-> посвященный)

+ return zink_batch_usage_is_unflasted (res-> obj-> пишет);

[VK_MAX_MEMORY_TYPES] + return zink_batch_usage_is_unflasted (res-> obj-> bo-> пишет);

}

статический встроенный логический тип [VK_MAX_MEMORY_TYPES] zink_resource_usage_matches ( const struct zink_resource res, const struct zink_batch_state bs)

{

– вернуть z ink_batch_usage_matches (res-> obj-> reads, bs) ||

– zink_batch_usage_matches (res-> obj-> пишет, bs); [VK_MAX_MEMORY_TYPES] + if (res-> obj-> выделенный)

+ return zink_batch_usage_matches (res-> obj-> reads, bs) ||

+ zink_batch_usage_matches (res-> obj-> пишет, bs);

+ return zink_bo_usage_matches (res-> obj-> bo, bs);

}

static inline bool

[VK_MAX_MEMORY_TYPES] zink_resource_has_usage (const struct zink_resource res)

{

– вернуть zink_batch_usage_exists (res-> obj-> читает) | |

– zink_batch_usage_exists (res-> obj-> пишет);

+ if (res-> obj-> преданный)

+ return zink_batch_usage_exists (res-> obj-> reads) ||

+ zink_batch_usage_exists (res-> obj-> пишет); [VK_MAX_MEMORY_TYPES] + return zink_bo_has_usage (res-> obj-> bo);

}

статический встроенный логический тип

zink_resource_has_unflasted_usage (const struct zink_resource res)

{

– вернуть zink_batch_usage_is_unflasted ( res-> obj-> читает) ||

– zink_batch_usage_is_unflasted (res-> obj-> пишет); [VK_MAX_MEMORY_TYPES] + if (res-> obj-> посвященный)

+ return zink_batch_usage_is_unfl ushed (res-> obj-> читает) ||

+ zink_batch_usage_is_unflasted (res-> obj-> пишет);

+ return zink_bo_has_unflasted_usage (res-> obj-> bo);

}

статический встроенный логический тип

zink_resource_usage_check_completion (struct zink_screen screen, struct zink_resource res, enum zink_resource_access доступ)

{

– если (доступ & ZINK_RESOURCE_ACCESS_READ &&! zink_screen_usage_check_completion (экран, res-> obj-> читает))

– вернуть false;

– if (access & ZINK_RESOURCE_ACCESS_WRITE &&! zink_screen_usage_check_completion (screen, res-> obj-> пишет))

– возвращение ложный;

– вернуть истину;

+ if (res-> obj-> посвященный) {

+ if (access & ZINK_RESOURCE_ACCESS_READ &&! zink_screen_usage_check_completion (screen, res-> obj-> reads))

+ return false;

+ if (access & ZINK_RESOURCE_ACCESS_WRITE &&! zink_screen_usage_check_completion (screen, res-> obj-> пишет))

+ return false;

+ вернуть истину;

+}

+ return zink_bo_usage_check_completion (экран, res-> obj-> bo, доступ);

[VK_MAX_MEMORY_TYPES]}

static inline void

zink_resource_usage_wait (struct zink_context ctx, struct zink_resource res, enum zink_resource_access access)

{

– если (доступ & ZINK_RESOURCE_ACCESS_READ)

– zink_batch_usage_wait (ctx, res-> obj-> читает);

– если (доступ & ZINK_RESOURCE_ACCESS_WRITE)

– zink_batch_usage_wait (ctx, res-> obj-> пишет);

+ if (res-> obj-> посвященный) {

+ if (access & ZINK_RESOURCE_ACCESS_READ)

+ zink_batch_usage_wait (ctx, res-> obj-> читает );

+ if (доступ & ZINK_RESOURCE_ACCESS_WRITE)

+ zink_batch_usage_wait (ctx, res-> obj-> пишет );

+} else

+ zink_bo_usage_wait (ctx, res-> obj-> bo, access);

}

static inline void

zink_resource_usage_set (struct zink_resource res, struct zink_batch_state bs, bool write)

{

– если (написать)

– zink_batch_usage_set (& res-> obj-> пишет, bs );

– еще

– zink_batch_usage_set (& res-> obj-> reads, bs);

+ if (res-> obj-> посвященный) {

+ if (написать)

[VK_MAX_MEMORY_TYPES] + zink_batch_usage_set (& res-> obj-> пишет, бс);

+ else

+ zink_batch_usage_set (& res-> obj-> читает, bs);

+} else

+ zink_bo_usage_set (res-> obj-> bo, bs, write);

}

static inline void

zink_resource_object_usage_unset (struct zink_resource_object obj, struct zink_batch_state bs)

{

– zink_batch_usage_unset (& obj -> читает, bs);

– zink_batch_usage_unset (& obj-> пишет, bs);

+ if (obj-> посвященный) {

+ zink_batch_usage_unset (& obj-> читает, bs);

+ zink_batch_usage_unset (& obj-> пишет, bs);

+} else

+ zink_bo_usage_unset (obj-> bo, bs);

}

#endif

@@ – 637, 8 + 637, 8 @@ zink_get_param (struct pipe_screen pscreen, enum pipe_cap param)

экран возврата-> info.feats.features.shaderCullDistance;

case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:

– / это минимум спецификации /

– экран возврата- > info.feats.features.sparseBinding? 73 1038: 0;

+

+ экран возврата-> info.feats.features.sparseBinding? ZINK_SPARSE_BUFFER_PAGE_SIZE: 0;

case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:

экран возврата-> info.props.limits.viewportSubPixelBits;

@@ – 1051, 24 + 1051, 6 @@ zink_is_format_supported ( struct pipe_screen pscreen,

}

статическая пустота

– resource_cache_entry_destroy (struct zink_screen screen, struct hash_entry he)

– {

– struct util_dynarray array = (void he-> dat a;

– util_dynarray_foreach (массив, структура mem_cache_entry, mc) {

– vkFreeMemory (screen-> dev, mc-> mem, NULL);

-}

– util_dynarray_fini (массив);

-}

– статическая пустота

zink_destroy_screen (struct pipe_screen pscreen)

{

struct zink_screen screen = zink_screen (pscreen) ;

@@ – 1606, 20 + 1109, 7 @@ zink_destroy_screen (struct pipe_screen pscreen)

}

#endif

[VK_MAX_MEMORY_TYPES] disk_cache_destroy (screen-> disk_cache);

– для (uint 40 _ t i = 0; я < (slabs-> info.mem_props.memoryHeapCount; ++ i) {

– simple_mtx_lock (& ​​screen-> mem.mem_cache_mtx);

[VK_MAX_MEMORY_TYPES] – hash_table_foreach (& screen-> mem.resource_mem_cache, он)

[VK_MAX_MEMORY_TYPES] – resource_cache_entry_destroy (экран, он);

– simple_mtx_unlock (& ​​screen-> mem.mem_cache_mtx);

[VK_MAX_MEMORY_TYPES] – simple_mtx_destroy (& screen-> mem .mem_cache_mtx);

[VK_MAX_MEMORY_TYPES] -}

+ zink_bo_deinit (экран);

util_live_shader_cache_deinit (& screen-> shaders);

if (screen-> sem)

@@ – 1904, 6+ 1892, 7 @@ zink_internal_create_screen (const struct pipe_screen_config config)

if (! zink_screen_resource_init (& screen-> base))

перейти к ошибке;

+ zink_bo_init (экран);

zink_screen_fence_init (& screen-> base);

zink_screen_in it_compiler (экран);

@@ – 2011, 6 + 1921, 31 @@ zink_internal_create_screen (const struct pipe_screen_config config)

if (screen-> info.have_KHR_timeline_semaphore)

zink_screen_init_semaphore (экран); [VK_MAX_MEMORY_TYPES] + memset (& screen-> heap_map, UINT8_MAX, sizeof (screen-> heap_map));

+ для (перечисление zink_heap i = 0; я

+ для (беззнакового j = 0; j < (slabs-> информации. mem_props.memoryTypeCount; j ++) {

+ VkMemoryPropertyFlags domains = vk_domain_from_heap (i);

+ if ((screen-> info.mem_props.memoryTypes [j]. propertyFlags & domains) == домены) {

+ assert (экран-> heap_map == UINT8_MAX);

+ экран-> heap_map = j;

+ перерыв;

+}

+}

+

+ / не найдено: использовать совместимую кучу /

+ if (screen-> heap_map == UINT8_MAX) {

+ / только кэшированная память сейчас имеет ошибку /

+ assert (i == ZINK_HEAP_HOST_VISIBLE_CACHED);

+ screen-> heap_map = screen-> heap_map [ZINK_HEAP_HOST_VISIBLE_ANY];

+}

+}

+

[VK_MAX_MEMORY_TYPES] simple_mtx_init (& screen-> surface_mtx, mtx_plain);

simple_mtx_init (& screen-> bufferview_mtx, mtx_plain);

simple_mtx_init (& screen-> framebuffer_mtx, mtx_plain);

[VK_MAX_MEMORY_TYPES] @@ – 40, 7 + 41, 8 @@

#include “util / simple_mtx.h”

#включают ” util / u_queue.h “

#include “ut il / u_live_shader_cache.h “

+ # include “pipebuffer / pb_cache.h”

+ # include “pipebuffer / pb_slab.h”

#включают

extern uint 38 _ t zink_debug;

@@ – 64 , 15 + 70, 20 @@ struct zink_program;

struct zink_shader;

enum zink_descriptor_type;

+ / это минимум спецификации /

+ # определить ZINK_SPARSE_BUFFER_PAGE_SIZE (72 1051)

+

#define ZINK_DEBUG_NIR 0x1

#define ZINK_DEBUG_SPIRV 0x2

#define ZINK_DEBUG_TGSI 0x4

#define ZINK_DEBUG_VALIDATION 0x8

+ # определить NUM_SLAB_ALLOCATORS 3

+

enum zink_descriptor_mode {

ZINK_DESCRIPTOR_MODE_AUTO,

ZINK_DESCRIPTOR_MODE_LAZY,

@@ – 70, 16 + 75, 6 @@ struct zink_modifier_prop {

VkDrmFormatModifierPropertiesEXT pDrmFormatModifierProperties;

};

– struct zink_mem_cache {

– simple_mtx_t mem_cache_mtx;

– struct hash_table resource_mem_cache;

– uint 46 _ t mem_cache_size;

– mem_cache_count без знака; [VK_MAX_MEMORY_TYPES] – };

struct zink_screen {

struct pipe_screen base;

bool с резьбой;

@@ – 134, 7 + 115, 24 @@ struct zink_screen {

[VK_MAX_MEMORY_TYPES] struct util_live_shader_cache шейдеры;

– struct zink_mem_cache mem;

+ struct {

+ struct pb_cache bo_cache;

+ struct pb_slabs bo_slabs [NUM_SLAB_ALLOCATORS];

+ min_alloc_size без знака;

+ struct hash_table bo_export_table;

+ simple_mtx_t bo_export_table_lock;

+ uint 38 _ t next_bo_unique_id;

+} pb;

+ uint8_t heap_map [VK_MAX_MEMORY_TYPES];

uint 66 _ t total_video_mem;

uint 72 _ t clip_video_mem;

Leave a comment

Your email address will not be published. Required fields are marked *

2 × 1 =