17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2021 Valve Corporation
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
217ec681f3Smrg * IN THE SOFTWARE.
227ec681f3Smrg *
237ec681f3Smrg * Authors:
247ec681f3Smrg *    Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
257ec681f3Smrg */
267ec681f3Smrg
277ec681f3Smrg#ifndef ZINK_BO_H
287ec681f3Smrg#define ZINK_BO_H
297ec681f3Smrg#include <vulkan/vulkan.h>
307ec681f3Smrg#include "pipebuffer/pb_cache.h"
317ec681f3Smrg#include "pipebuffer/pb_slab.h"
327ec681f3Smrg#include "zink_batch.h"
337ec681f3Smrg
347ec681f3Smrg#define VK_VIS_VRAM (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
357ec681f3Smrg#define VK_LAZY_VRAM (VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
367ec681f3Smrgenum zink_resource_access {
377ec681f3Smrg   ZINK_RESOURCE_ACCESS_READ = 1,
387ec681f3Smrg   ZINK_RESOURCE_ACCESS_WRITE = 32,
397ec681f3Smrg   ZINK_RESOURCE_ACCESS_RW = ZINK_RESOURCE_ACCESS_READ | ZINK_RESOURCE_ACCESS_WRITE,
407ec681f3Smrg};
417ec681f3Smrg
427ec681f3Smrg
437ec681f3Smrgenum zink_heap {
447ec681f3Smrg   ZINK_HEAP_DEVICE_LOCAL,
457ec681f3Smrg   ZINK_HEAP_DEVICE_LOCAL_SPARSE,
467ec681f3Smrg   ZINK_HEAP_DEVICE_LOCAL_LAZY,
477ec681f3Smrg   ZINK_HEAP_DEVICE_LOCAL_VISIBLE,
487ec681f3Smrg   ZINK_HEAP_HOST_VISIBLE_COHERENT,
497ec681f3Smrg   ZINK_HEAP_HOST_VISIBLE_CACHED,
507ec681f3Smrg   ZINK_HEAP_MAX,
517ec681f3Smrg};
527ec681f3Smrg
537ec681f3Smrgenum zink_alloc_flag {
547ec681f3Smrg   ZINK_ALLOC_SPARSE = 1<<0,
557ec681f3Smrg   ZINK_ALLOC_NO_SUBALLOC = 1<<1,
567ec681f3Smrg};
577ec681f3Smrg
587ec681f3Smrg
597ec681f3Smrgstruct zink_bo {
607ec681f3Smrg   struct pb_buffer base;
617ec681f3Smrg
627ec681f3Smrg   union {
637ec681f3Smrg      struct {
647ec681f3Smrg         void *cpu_ptr; /* for user_ptr and permanent maps */
657ec681f3Smrg         int map_count;
667ec681f3Smrg
677ec681f3Smrg         bool is_user_ptr;
687ec681f3Smrg         bool use_reusable_pool;
697ec681f3Smrg
707ec681f3Smrg         /* Whether buffer_get_handle or buffer_from_handle has been called,
717ec681f3Smrg          * it can only transition from false to true. Protected by lock.
727ec681f3Smrg          */
737ec681f3Smrg         bool is_shared;
747ec681f3Smrg      } real;
757ec681f3Smrg      struct {
767ec681f3Smrg         struct pb_slab_entry entry;
777ec681f3Smrg         struct zink_bo *real;
787ec681f3Smrg      } slab;
797ec681f3Smrg      struct {
807ec681f3Smrg         uint32_t num_va_pages;
817ec681f3Smrg         uint32_t num_backing_pages;
827ec681f3Smrg
837ec681f3Smrg         struct list_head backing;
847ec681f3Smrg
857ec681f3Smrg         /* Commitment information for each page of the virtual memory area. */
867ec681f3Smrg         struct zink_sparse_commitment *commitments;
877ec681f3Smrg      } sparse;
887ec681f3Smrg   } u;
897ec681f3Smrg
907ec681f3Smrg   VkDeviceMemory mem;
917ec681f3Smrg   uint64_t offset;
927ec681f3Smrg
937ec681f3Smrg   uint32_t unique_id;
947ec681f3Smrg
957ec681f3Smrg   simple_mtx_t lock;
967ec681f3Smrg
977ec681f3Smrg   struct zink_batch_usage *reads;
987ec681f3Smrg   struct zink_batch_usage *writes;
997ec681f3Smrg
1007ec681f3Smrg   struct pb_cache_entry cache_entry[];
1017ec681f3Smrg};
1027ec681f3Smrg
1037ec681f3Smrgstatic inline struct zink_bo *
1047ec681f3Smrgzink_bo(struct pb_buffer *pbuf)
1057ec681f3Smrg{
1067ec681f3Smrg   return (struct zink_bo*)pbuf;
1077ec681f3Smrg}
1087ec681f3Smrg
1097ec681f3Smrgstatic inline enum zink_alloc_flag
1107ec681f3Smrgzink_alloc_flags_from_heap(enum zink_heap heap)
1117ec681f3Smrg{
1127ec681f3Smrg   enum zink_alloc_flag flags = 0;
1137ec681f3Smrg   switch (heap) {
1147ec681f3Smrg   case ZINK_HEAP_DEVICE_LOCAL_SPARSE:
1157ec681f3Smrg      flags |= ZINK_ALLOC_SPARSE;
1167ec681f3Smrg      break;
1177ec681f3Smrg   default:
1187ec681f3Smrg      break;
1197ec681f3Smrg   }
1207ec681f3Smrg   return flags;
1217ec681f3Smrg}
1227ec681f3Smrg
1237ec681f3Smrgstatic inline VkMemoryPropertyFlags
1247ec681f3Smrgvk_domain_from_heap(enum zink_heap heap)
1257ec681f3Smrg{
1267ec681f3Smrg   VkMemoryPropertyFlags domains = 0;
1277ec681f3Smrg
1287ec681f3Smrg   switch (heap) {
1297ec681f3Smrg   case ZINK_HEAP_DEVICE_LOCAL:
1307ec681f3Smrg   case ZINK_HEAP_DEVICE_LOCAL_SPARSE:
1317ec681f3Smrg      domains = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1327ec681f3Smrg      break;
1337ec681f3Smrg   case ZINK_HEAP_DEVICE_LOCAL_LAZY:
1347ec681f3Smrg      domains = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1357ec681f3Smrg      break;
1367ec681f3Smrg   case ZINK_HEAP_DEVICE_LOCAL_VISIBLE:
1377ec681f3Smrg      domains = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1387ec681f3Smrg      break;
1397ec681f3Smrg   case ZINK_HEAP_HOST_VISIBLE_COHERENT:
1407ec681f3Smrg      domains = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
1417ec681f3Smrg      break;
1427ec681f3Smrg   case ZINK_HEAP_HOST_VISIBLE_CACHED:
1437ec681f3Smrg      domains = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
1447ec681f3Smrg      break;
1457ec681f3Smrg   default:
1467ec681f3Smrg      break;
1477ec681f3Smrg   }
1487ec681f3Smrg   return domains;
1497ec681f3Smrg}
1507ec681f3Smrg
1517ec681f3Smrgstatic inline enum zink_heap
1527ec681f3Smrgzink_heap_from_domain_flags(VkMemoryPropertyFlags domains, enum zink_alloc_flag flags)
1537ec681f3Smrg{
1547ec681f3Smrg   if (flags & ZINK_ALLOC_SPARSE)
1557ec681f3Smrg      return ZINK_HEAP_DEVICE_LOCAL_SPARSE;
1567ec681f3Smrg
1577ec681f3Smrg   if ((domains & VK_VIS_VRAM) == VK_VIS_VRAM)
1587ec681f3Smrg      return ZINK_HEAP_DEVICE_LOCAL_VISIBLE;
1597ec681f3Smrg
1607ec681f3Smrg   if (domains & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
1617ec681f3Smrg      return ZINK_HEAP_DEVICE_LOCAL;
1627ec681f3Smrg
1637ec681f3Smrg   if (domains & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
1647ec681f3Smrg      return ZINK_HEAP_HOST_VISIBLE_CACHED;
1657ec681f3Smrg
1667ec681f3Smrg   return ZINK_HEAP_HOST_VISIBLE_COHERENT;
1677ec681f3Smrg}
1687ec681f3Smrg
1697ec681f3Smrgbool
1707ec681f3Smrgzink_bo_init(struct zink_screen *screen);
1717ec681f3Smrg
1727ec681f3Smrgvoid
1737ec681f3Smrgzink_bo_deinit(struct zink_screen *screen);
1747ec681f3Smrg
1757ec681f3Smrgstruct pb_buffer *
1767ec681f3Smrgzink_bo_create(struct zink_screen *screen, uint64_t size, unsigned alignment, enum zink_heap heap, enum zink_alloc_flag flags, const void *pNext);
1777ec681f3Smrg
1787ec681f3Smrgstatic inline uint64_t
1797ec681f3Smrgzink_bo_get_offset(const struct zink_bo *bo)
1807ec681f3Smrg{
1817ec681f3Smrg   return bo->offset;
1827ec681f3Smrg}
1837ec681f3Smrg
1847ec681f3Smrgstatic inline VkDeviceMemory
1857ec681f3Smrgzink_bo_get_mem(const struct zink_bo *bo)
1867ec681f3Smrg{
1877ec681f3Smrg   return bo->mem ? bo->mem : bo->u.slab.real->mem;
1887ec681f3Smrg}
1897ec681f3Smrg
1907ec681f3Smrgstatic inline VkDeviceSize
1917ec681f3Smrgzink_bo_get_size(const struct zink_bo *bo)
1927ec681f3Smrg{
1937ec681f3Smrg   return bo->mem ? bo->base.size : bo->u.slab.real->base.size;
1947ec681f3Smrg}
1957ec681f3Smrg
1967ec681f3Smrgvoid *
1977ec681f3Smrgzink_bo_map(struct zink_screen *screen, struct zink_bo *bo);
1987ec681f3Smrgvoid
1997ec681f3Smrgzink_bo_unmap(struct zink_screen *screen, struct zink_bo *bo);
2007ec681f3Smrg
2017ec681f3Smrgbool
2027ec681f3Smrgzink_bo_commit(struct zink_screen *screen, struct zink_resource *res, uint32_t offset, uint32_t size, bool commit);
2037ec681f3Smrg
2047ec681f3Smrgstatic inline bool
2057ec681f3Smrgzink_bo_has_unflushed_usage(const struct zink_bo *bo)
2067ec681f3Smrg{
2077ec681f3Smrg   return zink_batch_usage_is_unflushed(bo->reads) ||
2087ec681f3Smrg          zink_batch_usage_is_unflushed(bo->writes);
2097ec681f3Smrg}
2107ec681f3Smrg
2117ec681f3Smrgstatic inline bool
2127ec681f3Smrgzink_bo_has_usage(const struct zink_bo *bo)
2137ec681f3Smrg{
2147ec681f3Smrg   return zink_batch_usage_exists(bo->reads) ||
2157ec681f3Smrg          zink_batch_usage_exists(bo->writes);
2167ec681f3Smrg}
2177ec681f3Smrg
2187ec681f3Smrgstatic inline bool
2197ec681f3Smrgzink_bo_usage_matches(const struct zink_bo *bo, const struct zink_batch_state *bs)
2207ec681f3Smrg{
2217ec681f3Smrg   return zink_batch_usage_matches(bo->reads, bs) ||
2227ec681f3Smrg          zink_batch_usage_matches(bo->writes, bs);
2237ec681f3Smrg}
2247ec681f3Smrg
2257ec681f3Smrgstatic inline bool
2267ec681f3Smrgzink_bo_usage_check_completion(struct zink_screen *screen, struct zink_bo *bo, enum zink_resource_access access)
2277ec681f3Smrg{
2287ec681f3Smrg   if (access & ZINK_RESOURCE_ACCESS_READ && !zink_screen_usage_check_completion(screen, bo->reads))
2297ec681f3Smrg      return false;
2307ec681f3Smrg   if (access & ZINK_RESOURCE_ACCESS_WRITE && !zink_screen_usage_check_completion(screen, bo->writes))
2317ec681f3Smrg      return false;
2327ec681f3Smrg   return true;
2337ec681f3Smrg}
2347ec681f3Smrg
2357ec681f3Smrgstatic inline void
2367ec681f3Smrgzink_bo_usage_wait(struct zink_context *ctx, struct zink_bo *bo, enum zink_resource_access access)
2377ec681f3Smrg{
2387ec681f3Smrg   if (access & ZINK_RESOURCE_ACCESS_READ)
2397ec681f3Smrg      zink_batch_usage_wait(ctx, bo->reads);
2407ec681f3Smrg   if (access & ZINK_RESOURCE_ACCESS_WRITE)
2417ec681f3Smrg      zink_batch_usage_wait(ctx, bo->writes);
2427ec681f3Smrg}
2437ec681f3Smrg
2447ec681f3Smrgstatic inline void
2457ec681f3Smrgzink_bo_usage_set(struct zink_bo *bo, struct zink_batch_state *bs, bool write)
2467ec681f3Smrg{
2477ec681f3Smrg   if (write)
2487ec681f3Smrg      zink_batch_usage_set(&bo->writes, bs);
2497ec681f3Smrg   else
2507ec681f3Smrg      zink_batch_usage_set(&bo->reads, bs);
2517ec681f3Smrg}
2527ec681f3Smrg
2537ec681f3Smrgstatic inline bool
2547ec681f3Smrgzink_bo_usage_unset(struct zink_bo *bo, struct zink_batch_state *bs)
2557ec681f3Smrg{
2567ec681f3Smrg   zink_batch_usage_unset(&bo->reads, bs);
2577ec681f3Smrg   zink_batch_usage_unset(&bo->writes, bs);
2587ec681f3Smrg   return bo->reads || bo->writes;
2597ec681f3Smrg}
2607ec681f3Smrg
2617ec681f3Smrg
2627ec681f3Smrgstatic inline void
2637ec681f3Smrgzink_bo_unref(struct zink_screen *screen, struct zink_bo *bo)
2647ec681f3Smrg{
2657ec681f3Smrg   struct pb_buffer *pbuf = &bo->base;
2667ec681f3Smrg   pb_reference_with_winsys(screen, &pbuf, NULL);
2677ec681f3Smrg}
2687ec681f3Smrg
2697ec681f3Smrg#endif
270