1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2018 Collabora Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "zink_resource.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "zink_batch.h" 27bf215546Sopenharmony_ci#include "zink_context.h" 28bf215546Sopenharmony_ci#include "zink_fence.h" 29bf215546Sopenharmony_ci#include "zink_program.h" 30bf215546Sopenharmony_ci#include "zink_screen.h" 31bf215546Sopenharmony_ci#include "zink_kopper.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_METAL_EXT 34bf215546Sopenharmony_ci#include "QuartzCore/CAMetalLayer.h" 35bf215546Sopenharmony_ci#endif 36bf215546Sopenharmony_ci#include "vulkan/wsi/wsi_common.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include "vk_format.h" 39bf215546Sopenharmony_ci#include "util/slab.h" 40bf215546Sopenharmony_ci#include "util/u_blitter.h" 41bf215546Sopenharmony_ci#include "util/u_debug.h" 42bf215546Sopenharmony_ci#include "util/format/u_format.h" 43bf215546Sopenharmony_ci#include "util/u_transfer_helper.h" 44bf215546Sopenharmony_ci#include "util/u_inlines.h" 45bf215546Sopenharmony_ci#include "util/u_memory.h" 46bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 47bf215546Sopenharmony_ci#include "util/os_file.h" 48bf215546Sopenharmony_ci#include "frontend/winsys_handle.h" 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci#if !defined(__APPLE__) 51bf215546Sopenharmony_ci#define ZINK_USE_DMABUF 52bf215546Sopenharmony_ci#endif 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci#if defined(ZINK_USE_DMABUF) && !defined(_WIN32) 55bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h" 56bf215546Sopenharmony_ci#else 57bf215546Sopenharmony_ci/* these won't actually be used */ 58bf215546Sopenharmony_ci#define DRM_FORMAT_MOD_INVALID 0 59bf215546Sopenharmony_ci#define DRM_FORMAT_MOD_LINEAR 0 60bf215546Sopenharmony_ci#endif 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci#if defined(__APPLE__) 63bf215546Sopenharmony_ci// Source of MVK_VERSION 64bf215546Sopenharmony_ci#include "MoltenVK/vk_mvk_moltenvk.h" 65bf215546Sopenharmony_ci#endif 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci#define ZINK_EXTERNAL_MEMORY_HANDLE 999 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic bool 70bf215546Sopenharmony_ciequals_ivci(const void *a, const void *b) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci const uint8_t *pa = a; 73bf215546Sopenharmony_ci const uint8_t *pb = b; 74bf215546Sopenharmony_ci size_t offset = offsetof(VkImageViewCreateInfo, flags); 75bf215546Sopenharmony_ci return memcmp(pa + offset, pb + offset, sizeof(VkImageViewCreateInfo) - offset) == 0; 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_cistatic bool 79bf215546Sopenharmony_ciequals_bvci(const void *a, const void *b) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci const uint8_t *pa = a; 82bf215546Sopenharmony_ci const uint8_t *pb = b; 83bf215546Sopenharmony_ci size_t offset = offsetof(VkBufferViewCreateInfo, flags); 84bf215546Sopenharmony_ci return memcmp(pa + offset, pb + offset, sizeof(VkBufferViewCreateInfo) - offset) == 0; 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cistatic void 88bf215546Sopenharmony_cizink_transfer_flush_region(struct pipe_context *pctx, 89bf215546Sopenharmony_ci struct pipe_transfer *ptrans, 90bf215546Sopenharmony_ci const struct pipe_box *box); 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_civoid 93bf215546Sopenharmony_cidebug_describe_zink_resource_object(char *buf, const struct zink_resource_object *ptr) 94bf215546Sopenharmony_ci{ 95bf215546Sopenharmony_ci sprintf(buf, "zink_resource_object"); 96bf215546Sopenharmony_ci} 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_civoid 99bf215546Sopenharmony_cizink_destroy_resource_object(struct zink_screen *screen, struct zink_resource_object *obj) 100bf215546Sopenharmony_ci{ 101bf215546Sopenharmony_ci if (obj->is_buffer) { 102bf215546Sopenharmony_ci VKSCR(DestroyBuffer)(screen->dev, obj->buffer, NULL); 103bf215546Sopenharmony_ci VKSCR(DestroyBuffer)(screen->dev, obj->storage_buffer, NULL); 104bf215546Sopenharmony_ci } else if (obj->dt) { 105bf215546Sopenharmony_ci zink_kopper_displaytarget_destroy(screen, obj->dt); 106bf215546Sopenharmony_ci } else if (!obj->is_aux) { 107bf215546Sopenharmony_ci VKSCR(DestroyImage)(screen->dev, obj->image, NULL); 108bf215546Sopenharmony_ci } else { 109bf215546Sopenharmony_ci#if defined(ZINK_USE_DMABUF) && !defined(_WIN32) 110bf215546Sopenharmony_ci close(obj->handle); 111bf215546Sopenharmony_ci#endif 112bf215546Sopenharmony_ci } 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci zink_descriptor_set_refs_clear(&obj->desc_set_refs, obj); 115bf215546Sopenharmony_ci if (obj->dt) { 116bf215546Sopenharmony_ci FREE(obj->bo); //this is a dummy struct 117bf215546Sopenharmony_ci } else 118bf215546Sopenharmony_ci zink_bo_unref(screen, obj->bo); 119bf215546Sopenharmony_ci FREE(obj); 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_cistatic void 123bf215546Sopenharmony_cizink_resource_destroy(struct pipe_screen *pscreen, 124bf215546Sopenharmony_ci struct pipe_resource *pres) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pscreen); 127bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 128bf215546Sopenharmony_ci if (pres->target == PIPE_BUFFER) { 129bf215546Sopenharmony_ci util_range_destroy(&res->valid_buffer_range); 130bf215546Sopenharmony_ci util_idalloc_mt_free(&screen->buffer_ids, res->base.buffer_id_unique); 131bf215546Sopenharmony_ci assert(!_mesa_hash_table_num_entries(&res->bufferview_cache)); 132bf215546Sopenharmony_ci simple_mtx_destroy(&res->bufferview_mtx); 133bf215546Sopenharmony_ci ralloc_free(res->bufferview_cache.table); 134bf215546Sopenharmony_ci } else { 135bf215546Sopenharmony_ci assert(!_mesa_hash_table_num_entries(&res->surface_cache)); 136bf215546Sopenharmony_ci simple_mtx_destroy(&res->surface_mtx); 137bf215546Sopenharmony_ci ralloc_free(res->surface_cache.table); 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci /* no need to do anything for the caches, these objects own the resource lifetimes */ 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci zink_resource_object_reference(screen, &res->obj, NULL); 142bf215546Sopenharmony_ci threaded_resource_deinit(pres); 143bf215546Sopenharmony_ci FREE_CL(res); 144bf215546Sopenharmony_ci} 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_cistatic VkImageAspectFlags 147bf215546Sopenharmony_ciaspect_from_format(enum pipe_format fmt) 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(fmt)) { 150bf215546Sopenharmony_ci VkImageAspectFlags aspect = 0; 151bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(fmt); 152bf215546Sopenharmony_ci if (util_format_has_depth(desc)) 153bf215546Sopenharmony_ci aspect |= VK_IMAGE_ASPECT_DEPTH_BIT; 154bf215546Sopenharmony_ci if (util_format_has_stencil(desc)) 155bf215546Sopenharmony_ci aspect |= VK_IMAGE_ASPECT_STENCIL_BIT; 156bf215546Sopenharmony_ci return aspect; 157bf215546Sopenharmony_ci } else 158bf215546Sopenharmony_ci return VK_IMAGE_ASPECT_COLOR_BIT; 159bf215546Sopenharmony_ci} 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_cistatic VkBufferCreateInfo 162bf215546Sopenharmony_cicreate_bci(struct zink_screen *screen, const struct pipe_resource *templ, unsigned bind) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci VkBufferCreateInfo bci; 165bf215546Sopenharmony_ci bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 166bf215546Sopenharmony_ci bci.pNext = NULL; 167bf215546Sopenharmony_ci bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 168bf215546Sopenharmony_ci bci.queueFamilyIndexCount = 0; 169bf215546Sopenharmony_ci bci.pQueueFamilyIndices = NULL; 170bf215546Sopenharmony_ci bci.size = templ->width0; 171bf215546Sopenharmony_ci bci.flags = 0; 172bf215546Sopenharmony_ci assert(bci.size > 0); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | 175bf215546Sopenharmony_ci VK_BUFFER_USAGE_TRANSFER_DST_BIT | 176bf215546Sopenharmony_ci VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci bci.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | 179bf215546Sopenharmony_ci VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | 180bf215546Sopenharmony_ci VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | 181bf215546Sopenharmony_ci VK_BUFFER_USAGE_INDEX_BUFFER_BIT | 182bf215546Sopenharmony_ci VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | 183bf215546Sopenharmony_ci VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | 184bf215546Sopenharmony_ci VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci if (bind & PIPE_BIND_SHADER_IMAGE) 187bf215546Sopenharmony_ci bci.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci if (bind & PIPE_BIND_QUERY_BUFFER) 190bf215546Sopenharmony_ci bci.usage |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT; 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci if (templ->flags & PIPE_RESOURCE_FLAG_SPARSE) 193bf215546Sopenharmony_ci bci.flags |= VK_BUFFER_CREATE_SPARSE_BINDING_BIT; 194bf215546Sopenharmony_ci return bci; 195bf215546Sopenharmony_ci} 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_cistatic bool 198bf215546Sopenharmony_cicheck_ici(struct zink_screen *screen, VkImageCreateInfo *ici, uint64_t modifier) 199bf215546Sopenharmony_ci{ 200bf215546Sopenharmony_ci VkImageFormatProperties image_props; 201bf215546Sopenharmony_ci VkResult ret; 202bf215546Sopenharmony_ci assert(modifier == DRM_FORMAT_MOD_INVALID || 203bf215546Sopenharmony_ci (VKSCR(GetPhysicalDeviceImageFormatProperties2) && screen->info.have_EXT_image_drm_format_modifier)); 204bf215546Sopenharmony_ci if (VKSCR(GetPhysicalDeviceImageFormatProperties2)) { 205bf215546Sopenharmony_ci VkImageFormatProperties2 props2; 206bf215546Sopenharmony_ci props2.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; 207bf215546Sopenharmony_ci props2.pNext = NULL; 208bf215546Sopenharmony_ci VkSamplerYcbcrConversionImageFormatProperties ycbcr_props; 209bf215546Sopenharmony_ci ycbcr_props.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES; 210bf215546Sopenharmony_ci ycbcr_props.pNext = NULL; 211bf215546Sopenharmony_ci if (screen->info.have_KHR_sampler_ycbcr_conversion) 212bf215546Sopenharmony_ci props2.pNext = &ycbcr_props; 213bf215546Sopenharmony_ci VkPhysicalDeviceImageFormatInfo2 info; 214bf215546Sopenharmony_ci info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; 215bf215546Sopenharmony_ci /* possibly VkImageFormatListCreateInfo */ 216bf215546Sopenharmony_ci info.pNext = ici->pNext; 217bf215546Sopenharmony_ci info.format = ici->format; 218bf215546Sopenharmony_ci info.type = ici->imageType; 219bf215546Sopenharmony_ci info.tiling = ici->tiling; 220bf215546Sopenharmony_ci info.usage = ici->usage; 221bf215546Sopenharmony_ci info.flags = ici->flags; 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info; 224bf215546Sopenharmony_ci if (modifier != DRM_FORMAT_MOD_INVALID) { 225bf215546Sopenharmony_ci mod_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT; 226bf215546Sopenharmony_ci mod_info.pNext = info.pNext; 227bf215546Sopenharmony_ci mod_info.drmFormatModifier = modifier; 228bf215546Sopenharmony_ci mod_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 229bf215546Sopenharmony_ci mod_info.queueFamilyIndexCount = 0; 230bf215546Sopenharmony_ci info.pNext = &mod_info; 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci ret = VKSCR(GetPhysicalDeviceImageFormatProperties2)(screen->pdev, &info, &props2); 234bf215546Sopenharmony_ci /* this is using VK_IMAGE_CREATE_EXTENDED_USAGE_BIT and can't be validated */ 235bf215546Sopenharmony_ci if (vk_format_aspects(ici->format) & VK_IMAGE_ASPECT_PLANE_1_BIT) 236bf215546Sopenharmony_ci ret = VK_SUCCESS; 237bf215546Sopenharmony_ci image_props = props2.imageFormatProperties; 238bf215546Sopenharmony_ci } else 239bf215546Sopenharmony_ci ret = VKSCR(GetPhysicalDeviceImageFormatProperties)(screen->pdev, ici->format, ici->imageType, 240bf215546Sopenharmony_ci ici->tiling, ici->usage, ici->flags, &image_props); 241bf215546Sopenharmony_ci if (ret != VK_SUCCESS) 242bf215546Sopenharmony_ci return false; 243bf215546Sopenharmony_ci if (ici->extent.depth > image_props.maxExtent.depth || 244bf215546Sopenharmony_ci ici->extent.height > image_props.maxExtent.height || 245bf215546Sopenharmony_ci ici->extent.width > image_props.maxExtent.width) 246bf215546Sopenharmony_ci return false; 247bf215546Sopenharmony_ci if (ici->mipLevels > image_props.maxMipLevels) 248bf215546Sopenharmony_ci return false; 249bf215546Sopenharmony_ci if (ici->arrayLayers > image_props.maxArrayLayers) 250bf215546Sopenharmony_ci return false; 251bf215546Sopenharmony_ci return true; 252bf215546Sopenharmony_ci} 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_cistatic VkImageUsageFlags 255bf215546Sopenharmony_ciget_image_usage_for_feats(struct zink_screen *screen, VkFormatFeatureFlags feats, const struct pipe_resource *templ, unsigned bind, bool *need_extended) 256bf215546Sopenharmony_ci{ 257bf215546Sopenharmony_ci VkImageUsageFlags usage = 0; 258bf215546Sopenharmony_ci bool is_planar = util_format_get_num_planes(templ->format) > 1; 259bf215546Sopenharmony_ci *need_extended = false; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci if (bind & ZINK_BIND_TRANSIENT) 262bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; 263bf215546Sopenharmony_ci else { 264bf215546Sopenharmony_ci /* sadly, gallium doesn't let us know if it'll ever need this, so we have to assume */ 265bf215546Sopenharmony_ci if (is_planar || (feats & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) 266bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 267bf215546Sopenharmony_ci if (is_planar || (feats & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) 268bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; 269bf215546Sopenharmony_ci if (feats & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) 270bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_SAMPLED_BIT; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci if ((is_planar || (feats & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) && (bind & PIPE_BIND_SHADER_IMAGE)) { 273bf215546Sopenharmony_ci assert(templ->nr_samples <= 1 || screen->info.feats.features.shaderStorageImageMultisample); 274bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_STORAGE_BIT; 275bf215546Sopenharmony_ci } 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci if (bind & PIPE_BIND_RENDER_TARGET) { 279bf215546Sopenharmony_ci if (feats & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) { 280bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 281bf215546Sopenharmony_ci if ((bind & (PIPE_BIND_LINEAR | PIPE_BIND_SHARED)) != (PIPE_BIND_LINEAR | PIPE_BIND_SHARED)) 282bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 283bf215546Sopenharmony_ci } else { 284bf215546Sopenharmony_ci /* trust that gallium isn't going to give us anything wild */ 285bf215546Sopenharmony_ci *need_extended = true; 286bf215546Sopenharmony_ci return 0; 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci } else if ((bind & PIPE_BIND_SAMPLER_VIEW) && !util_format_is_depth_or_stencil(templ->format)) { 289bf215546Sopenharmony_ci if (!(feats & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) { 290bf215546Sopenharmony_ci /* ensure we can u_blitter this later */ 291bf215546Sopenharmony_ci *need_extended = true; 292bf215546Sopenharmony_ci return 0; 293bf215546Sopenharmony_ci } 294bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 295bf215546Sopenharmony_ci } 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci if (bind & PIPE_BIND_DEPTH_STENCIL) { 298bf215546Sopenharmony_ci if (feats & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) 299bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 300bf215546Sopenharmony_ci else 301bf215546Sopenharmony_ci return 0; 302bf215546Sopenharmony_ci /* this is unlikely to occur and has been included for completeness */ 303bf215546Sopenharmony_ci } else if (bind & PIPE_BIND_SAMPLER_VIEW && !(usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) { 304bf215546Sopenharmony_ci if (feats & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) 305bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 306bf215546Sopenharmony_ci else 307bf215546Sopenharmony_ci return 0; 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci if (bind & PIPE_BIND_STREAM_OUTPUT) 311bf215546Sopenharmony_ci usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci return usage; 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_cistatic VkFormatFeatureFlags 317bf215546Sopenharmony_cifind_modifier_feats(const struct zink_modifier_prop *prop, uint64_t modifier, uint64_t *mod) 318bf215546Sopenharmony_ci{ 319bf215546Sopenharmony_ci for (unsigned j = 0; j < prop->drmFormatModifierCount; j++) { 320bf215546Sopenharmony_ci if (prop->pDrmFormatModifierProperties[j].drmFormatModifier == modifier) { 321bf215546Sopenharmony_ci *mod = modifier; 322bf215546Sopenharmony_ci return prop->pDrmFormatModifierProperties[j].drmFormatModifierTilingFeatures; 323bf215546Sopenharmony_ci } 324bf215546Sopenharmony_ci } 325bf215546Sopenharmony_ci return 0; 326bf215546Sopenharmony_ci} 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci/* If the driver can't do mutable with this ICI, then try again after removing mutable (and 329bf215546Sopenharmony_ci * thus also the list of formats we might might mutate to) 330bf215546Sopenharmony_ci */ 331bf215546Sopenharmony_cistatic bool 332bf215546Sopenharmony_cidouble_check_ici(struct zink_screen *screen, VkImageCreateInfo *ici, VkImageUsageFlags usage, uint64_t *mod) 333bf215546Sopenharmony_ci{ 334bf215546Sopenharmony_ci if (!usage) 335bf215546Sopenharmony_ci return false; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci const void *pNext = ici->pNext; 338bf215546Sopenharmony_ci ici->usage = usage; 339bf215546Sopenharmony_ci if (check_ici(screen, ici, *mod)) 340bf215546Sopenharmony_ci return true; 341bf215546Sopenharmony_ci if (pNext) { 342bf215546Sopenharmony_ci ici->pNext = NULL; 343bf215546Sopenharmony_ci ici->flags &= ~VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; 344bf215546Sopenharmony_ci if (check_ici(screen, ici, *mod)) 345bf215546Sopenharmony_ci return true; 346bf215546Sopenharmony_ci ici->pNext = pNext; 347bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci return false; 350bf215546Sopenharmony_ci} 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_cistatic VkImageUsageFlags 353bf215546Sopenharmony_ciget_image_usage(struct zink_screen *screen, VkImageCreateInfo *ici, const struct pipe_resource *templ, unsigned bind, unsigned modifiers_count, const uint64_t *modifiers, uint64_t *mod) 354bf215546Sopenharmony_ci{ 355bf215546Sopenharmony_ci VkImageTiling tiling = ici->tiling; 356bf215546Sopenharmony_ci bool need_extended = false; 357bf215546Sopenharmony_ci *mod = DRM_FORMAT_MOD_INVALID; 358bf215546Sopenharmony_ci if (modifiers_count) { 359bf215546Sopenharmony_ci bool have_linear = false; 360bf215546Sopenharmony_ci const struct zink_modifier_prop *prop = &screen->modifier_props[templ->format]; 361bf215546Sopenharmony_ci assert(tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT); 362bf215546Sopenharmony_ci for (unsigned i = 0; i < modifiers_count; i++) { 363bf215546Sopenharmony_ci if (modifiers[i] == DRM_FORMAT_MOD_LINEAR) { 364bf215546Sopenharmony_ci have_linear = true; 365bf215546Sopenharmony_ci if (!screen->info.have_EXT_image_drm_format_modifier) 366bf215546Sopenharmony_ci break; 367bf215546Sopenharmony_ci continue; 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci VkFormatFeatureFlags feats = find_modifier_feats(prop, modifiers[i], mod); 370bf215546Sopenharmony_ci if (feats) { 371bf215546Sopenharmony_ci VkImageUsageFlags usage = get_image_usage_for_feats(screen, feats, templ, bind, &need_extended); 372bf215546Sopenharmony_ci assert(!need_extended); 373bf215546Sopenharmony_ci if (double_check_ici(screen, ici, usage, mod)) 374bf215546Sopenharmony_ci return usage; 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci } 377bf215546Sopenharmony_ci /* only try linear if no other options available */ 378bf215546Sopenharmony_ci if (have_linear) { 379bf215546Sopenharmony_ci VkFormatFeatureFlags feats = find_modifier_feats(prop, DRM_FORMAT_MOD_LINEAR, mod); 380bf215546Sopenharmony_ci if (feats) { 381bf215546Sopenharmony_ci VkImageUsageFlags usage = get_image_usage_for_feats(screen, feats, templ, bind, &need_extended); 382bf215546Sopenharmony_ci assert(!need_extended); 383bf215546Sopenharmony_ci if (double_check_ici(screen, ici, usage, mod)) 384bf215546Sopenharmony_ci return usage; 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci } 387bf215546Sopenharmony_ci } else 388bf215546Sopenharmony_ci { 389bf215546Sopenharmony_ci VkFormatProperties props = screen->format_props[templ->format]; 390bf215546Sopenharmony_ci VkFormatFeatureFlags feats = tiling == VK_IMAGE_TILING_LINEAR ? props.linearTilingFeatures : props.optimalTilingFeatures; 391bf215546Sopenharmony_ci if (ici->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) 392bf215546Sopenharmony_ci feats = UINT32_MAX; 393bf215546Sopenharmony_ci VkImageUsageFlags usage = get_image_usage_for_feats(screen, feats, templ, bind, &need_extended); 394bf215546Sopenharmony_ci if (need_extended) { 395bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; 396bf215546Sopenharmony_ci feats = UINT32_MAX; 397bf215546Sopenharmony_ci usage = get_image_usage_for_feats(screen, feats, templ, bind, &need_extended); 398bf215546Sopenharmony_ci } 399bf215546Sopenharmony_ci if (double_check_ici(screen, ici, usage, mod)) 400bf215546Sopenharmony_ci return usage; 401bf215546Sopenharmony_ci } 402bf215546Sopenharmony_ci *mod = DRM_FORMAT_MOD_INVALID; 403bf215546Sopenharmony_ci return 0; 404bf215546Sopenharmony_ci} 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_cistatic uint64_t 407bf215546Sopenharmony_cicreate_ici(struct zink_screen *screen, VkImageCreateInfo *ici, const struct pipe_resource *templ, bool dmabuf, unsigned bind, unsigned modifiers_count, const uint64_t *modifiers, bool *success) 408bf215546Sopenharmony_ci{ 409bf215546Sopenharmony_ci ici->sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 410bf215546Sopenharmony_ci /* pNext may already be set */ 411bf215546Sopenharmony_ci if (util_format_get_num_planes(templ->format) > 1) 412bf215546Sopenharmony_ci ici->flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; 413bf215546Sopenharmony_ci else 414bf215546Sopenharmony_ci ici->flags = modifiers_count || dmabuf || bind & (PIPE_BIND_SCANOUT | PIPE_BIND_DEPTH_STENCIL) ? 0 : VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; 415bf215546Sopenharmony_ci if (ici->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) 416bf215546Sopenharmony_ci /* unset VkImageFormatListCreateInfo if mutable */ 417bf215546Sopenharmony_ci ici->pNext = NULL; 418bf215546Sopenharmony_ci else if (ici->pNext) 419bf215546Sopenharmony_ci /* add mutable if VkImageFormatListCreateInfo */ 420bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; 421bf215546Sopenharmony_ci ici->usage = 0; 422bf215546Sopenharmony_ci ici->queueFamilyIndexCount = 0; 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci if (templ->flags & PIPE_RESOURCE_FLAG_SPARSE) 425bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT; 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci bool need_2D = false; 428bf215546Sopenharmony_ci switch (templ->target) { 429bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 430bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 431bf215546Sopenharmony_ci if (templ->flags & PIPE_RESOURCE_FLAG_SPARSE) 432bf215546Sopenharmony_ci need_2D |= screen->need_2D_sparse; 433bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(templ->format)) 434bf215546Sopenharmony_ci need_2D |= screen->need_2D_zs; 435bf215546Sopenharmony_ci ici->imageType = need_2D ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_1D; 436bf215546Sopenharmony_ci break; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 439bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 440bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 441bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 442bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 443bf215546Sopenharmony_ci ici->imageType = VK_IMAGE_TYPE_2D; 444bf215546Sopenharmony_ci break; 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 447bf215546Sopenharmony_ci ici->imageType = VK_IMAGE_TYPE_3D; 448bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; 449bf215546Sopenharmony_ci if (screen->info.have_EXT_image_2d_view_of_3d) 450bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT; 451bf215546Sopenharmony_ci break; 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci case PIPE_BUFFER: 454bf215546Sopenharmony_ci unreachable("PIPE_BUFFER should already be handled"); 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci default: 457bf215546Sopenharmony_ci unreachable("Unknown target"); 458bf215546Sopenharmony_ci } 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci if (screen->info.have_EXT_sample_locations && 461bf215546Sopenharmony_ci bind & PIPE_BIND_DEPTH_STENCIL && 462bf215546Sopenharmony_ci util_format_has_depth(util_format_description(templ->format))) 463bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT; 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci ici->format = zink_get_format(screen, templ->format); 466bf215546Sopenharmony_ci ici->extent.width = templ->width0; 467bf215546Sopenharmony_ci ici->extent.height = templ->height0; 468bf215546Sopenharmony_ci ici->extent.depth = templ->depth0; 469bf215546Sopenharmony_ci ici->mipLevels = templ->last_level + 1; 470bf215546Sopenharmony_ci ici->arrayLayers = MAX2(templ->array_size, 1); 471bf215546Sopenharmony_ci ici->samples = templ->nr_samples ? templ->nr_samples : VK_SAMPLE_COUNT_1_BIT; 472bf215546Sopenharmony_ci ici->tiling = screen->info.have_EXT_image_drm_format_modifier && modifiers_count ? 473bf215546Sopenharmony_ci VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : 474bf215546Sopenharmony_ci bind & (PIPE_BIND_LINEAR | ZINK_BIND_DMABUF) ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; 475bf215546Sopenharmony_ci ici->sharingMode = VK_SHARING_MODE_EXCLUSIVE; 476bf215546Sopenharmony_ci ici->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci /* sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the following conditions is true: 479bf215546Sopenharmony_ci * - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT 480bf215546Sopenharmony_ci * 481bf215546Sopenharmony_ci * 44.1.1. Supported Sample Counts 482bf215546Sopenharmony_ci */ 483bf215546Sopenharmony_ci bool want_cube = ici->samples == 1 && 484bf215546Sopenharmony_ci (templ->target == PIPE_TEXTURE_CUBE || 485bf215546Sopenharmony_ci templ->target == PIPE_TEXTURE_CUBE_ARRAY || 486bf215546Sopenharmony_ci (templ->target == PIPE_TEXTURE_2D_ARRAY && ici->extent.width == ici->extent.height && ici->arrayLayers >= 6)); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci if (templ->target == PIPE_TEXTURE_CUBE) 489bf215546Sopenharmony_ci ici->arrayLayers *= 6; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci if (templ->usage == PIPE_USAGE_STAGING && 492bf215546Sopenharmony_ci templ->format != PIPE_FORMAT_B4G4R4A4_UNORM && 493bf215546Sopenharmony_ci templ->format != PIPE_FORMAT_B4G4R4A4_UINT) 494bf215546Sopenharmony_ci ici->tiling = VK_IMAGE_TILING_LINEAR; 495bf215546Sopenharmony_ci if (ici->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) 496bf215546Sopenharmony_ci modifiers_count = 0; 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci bool first = true; 499bf215546Sopenharmony_ci bool tried[2] = {0}; 500bf215546Sopenharmony_ci uint64_t mod = DRM_FORMAT_MOD_INVALID; 501bf215546Sopenharmony_ciretry: 502bf215546Sopenharmony_ci while (!ici->usage) { 503bf215546Sopenharmony_ci if (!first) { 504bf215546Sopenharmony_ci switch (ici->tiling) { 505bf215546Sopenharmony_ci case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: 506bf215546Sopenharmony_ci ici->tiling = VK_IMAGE_TILING_OPTIMAL; 507bf215546Sopenharmony_ci modifiers_count = 0; 508bf215546Sopenharmony_ci break; 509bf215546Sopenharmony_ci case VK_IMAGE_TILING_OPTIMAL: 510bf215546Sopenharmony_ci ici->tiling = VK_IMAGE_TILING_LINEAR; 511bf215546Sopenharmony_ci break; 512bf215546Sopenharmony_ci case VK_IMAGE_TILING_LINEAR: 513bf215546Sopenharmony_ci if (bind & PIPE_BIND_LINEAR) { 514bf215546Sopenharmony_ci *success = false; 515bf215546Sopenharmony_ci return DRM_FORMAT_MOD_INVALID; 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci ici->tiling = VK_IMAGE_TILING_OPTIMAL; 518bf215546Sopenharmony_ci break; 519bf215546Sopenharmony_ci default: 520bf215546Sopenharmony_ci unreachable("unhandled tiling mode"); 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci if (tried[ici->tiling]) { 523bf215546Sopenharmony_ci if (ici->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) { 524bf215546Sopenharmony_ci *success = false; 525bf215546Sopenharmony_ci return DRM_FORMAT_MOD_INVALID; 526bf215546Sopenharmony_ci } 527bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; 528bf215546Sopenharmony_ci tried[0] = false; 529bf215546Sopenharmony_ci tried[1] = false; 530bf215546Sopenharmony_ci first = true; 531bf215546Sopenharmony_ci goto retry; 532bf215546Sopenharmony_ci } 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci ici->usage = get_image_usage(screen, ici, templ, bind, modifiers_count, modifiers, &mod); 535bf215546Sopenharmony_ci first = false; 536bf215546Sopenharmony_ci if (ici->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) 537bf215546Sopenharmony_ci tried[ici->tiling] = true; 538bf215546Sopenharmony_ci } 539bf215546Sopenharmony_ci if (want_cube) { 540bf215546Sopenharmony_ci ici->flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; 541bf215546Sopenharmony_ci if (get_image_usage(screen, ici, templ, bind, modifiers_count, modifiers, &mod) != ici->usage) 542bf215546Sopenharmony_ci ici->flags &= ~VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; 543bf215546Sopenharmony_ci } 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ci *success = true; 546bf215546Sopenharmony_ci return mod; 547bf215546Sopenharmony_ci} 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_cistatic struct zink_resource_object * 550bf215546Sopenharmony_ciresource_object_create(struct zink_screen *screen, const struct pipe_resource *templ, struct winsys_handle *whandle, bool *optimal_tiling, 551bf215546Sopenharmony_ci const uint64_t *modifiers, int modifiers_count, const void *loader_private) 552bf215546Sopenharmony_ci{ 553bf215546Sopenharmony_ci struct zink_resource_object *obj = CALLOC_STRUCT(zink_resource_object); 554bf215546Sopenharmony_ci if (!obj) 555bf215546Sopenharmony_ci return NULL; 556bf215546Sopenharmony_ci obj->last_dt_idx = obj->dt_idx = UINT32_MAX; //TODO: unionize 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci VkMemoryRequirements reqs = {0}; 559bf215546Sopenharmony_ci VkMemoryPropertyFlags flags; 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci /* figure out aux plane count */ 562bf215546Sopenharmony_ci if (whandle && whandle->plane >= util_format_get_num_planes(whandle->format)) 563bf215546Sopenharmony_ci obj->is_aux = true; 564bf215546Sopenharmony_ci struct pipe_resource *pnext = templ->next; 565bf215546Sopenharmony_ci for (obj->plane_count = 1; pnext; obj->plane_count++, pnext = pnext->next) { 566bf215546Sopenharmony_ci struct zink_resource *next = zink_resource(pnext); 567bf215546Sopenharmony_ci if (!next->obj->is_aux) 568bf215546Sopenharmony_ci break; 569bf215546Sopenharmony_ci } 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci bool need_dedicated = false; 572bf215546Sopenharmony_ci bool shared = templ->bind & PIPE_BIND_SHARED; 573bf215546Sopenharmony_ci#if !defined(_WIN32) 574bf215546Sopenharmony_ci VkExternalMemoryHandleTypeFlags export_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; 575bf215546Sopenharmony_ci#else 576bf215546Sopenharmony_ci VkExternalMemoryHandleTypeFlags export_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; 577bf215546Sopenharmony_ci#endif 578bf215546Sopenharmony_ci unsigned num_planes = util_format_get_num_planes(templ->format); 579bf215546Sopenharmony_ci VkImageAspectFlags plane_aspects[] = { 580bf215546Sopenharmony_ci VK_IMAGE_ASPECT_PLANE_0_BIT, 581bf215546Sopenharmony_ci VK_IMAGE_ASPECT_PLANE_1_BIT, 582bf215546Sopenharmony_ci VK_IMAGE_ASPECT_PLANE_2_BIT, 583bf215546Sopenharmony_ci }; 584bf215546Sopenharmony_ci VkExternalMemoryHandleTypeFlags external = 0; 585bf215546Sopenharmony_ci bool needs_export = (templ->bind & (ZINK_BIND_VIDEO | ZINK_BIND_DMABUF)) != 0; 586bf215546Sopenharmony_ci if (whandle) { 587bf215546Sopenharmony_ci if (whandle->type == WINSYS_HANDLE_TYPE_FD || whandle->type == ZINK_EXTERNAL_MEMORY_HANDLE) 588bf215546Sopenharmony_ci needs_export |= true; 589bf215546Sopenharmony_ci else 590bf215546Sopenharmony_ci unreachable("unknown handle type"); 591bf215546Sopenharmony_ci } 592bf215546Sopenharmony_ci if (needs_export) { 593bf215546Sopenharmony_ci if (whandle && whandle->type == ZINK_EXTERNAL_MEMORY_HANDLE) { 594bf215546Sopenharmony_ci#if !defined(_WIN32) 595bf215546Sopenharmony_ci external = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; 596bf215546Sopenharmony_ci#else 597bf215546Sopenharmony_ci external = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; 598bf215546Sopenharmony_ci#endif 599bf215546Sopenharmony_ci } else { 600bf215546Sopenharmony_ci external = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 601bf215546Sopenharmony_ci export_types |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 602bf215546Sopenharmony_ci } 603bf215546Sopenharmony_ci } 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci /* we may export WINSYS_HANDLE_TYPE_FD handle which is dma-buf */ 606bf215546Sopenharmony_ci if (shared && screen->info.have_EXT_external_memory_dma_buf) 607bf215546Sopenharmony_ci export_types |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci pipe_reference_init(&obj->reference, 1); 610bf215546Sopenharmony_ci util_dynarray_init(&obj->desc_set_refs.refs, NULL); 611bf215546Sopenharmony_ci if (loader_private) { 612bf215546Sopenharmony_ci obj->bo = CALLOC_STRUCT(zink_bo); 613bf215546Sopenharmony_ci obj->transfer_dst = true; 614bf215546Sopenharmony_ci return obj; 615bf215546Sopenharmony_ci } else if (templ->target == PIPE_BUFFER) { 616bf215546Sopenharmony_ci VkBufferCreateInfo bci = create_bci(screen, templ, templ->bind); 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci if (VKSCR(CreateBuffer)(screen->dev, &bci, NULL, &obj->buffer) != VK_SUCCESS) { 619bf215546Sopenharmony_ci mesa_loge("ZINK: vkCreateBuffer failed"); 620bf215546Sopenharmony_ci goto fail1; 621bf215546Sopenharmony_ci } 622bf215546Sopenharmony_ci 623bf215546Sopenharmony_ci if (!(templ->bind & PIPE_BIND_SHADER_IMAGE)) { 624bf215546Sopenharmony_ci bci.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; 625bf215546Sopenharmony_ci if (VKSCR(CreateBuffer)(screen->dev, &bci, NULL, &obj->storage_buffer) != VK_SUCCESS) { 626bf215546Sopenharmony_ci mesa_loge("ZINK: vkCreateBuffer failed"); 627bf215546Sopenharmony_ci goto fail2; 628bf215546Sopenharmony_ci } 629bf215546Sopenharmony_ci } 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci VKSCR(GetBufferMemoryRequirements)(screen->dev, obj->buffer, &reqs); 632bf215546Sopenharmony_ci if (templ->usage == PIPE_USAGE_STAGING) 633bf215546Sopenharmony_ci flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; 634bf215546Sopenharmony_ci else if (templ->usage == PIPE_USAGE_STREAM) 635bf215546Sopenharmony_ci flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 636bf215546Sopenharmony_ci else if (templ->usage == PIPE_USAGE_IMMUTABLE) 637bf215546Sopenharmony_ci flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 638bf215546Sopenharmony_ci else 639bf215546Sopenharmony_ci flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 640bf215546Sopenharmony_ci obj->is_buffer = true; 641bf215546Sopenharmony_ci obj->transfer_dst = true; 642bf215546Sopenharmony_ci } else { 643bf215546Sopenharmony_ci bool winsys_modifier = (export_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) && whandle && whandle->modifier != DRM_FORMAT_MOD_INVALID; 644bf215546Sopenharmony_ci uint64_t mods[10]; 645bf215546Sopenharmony_ci bool try_modifiers = false; 646bf215546Sopenharmony_ci if ((export_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) && 647bf215546Sopenharmony_ci whandle && whandle->modifier == DRM_FORMAT_MOD_INVALID && whandle->stride) { 648bf215546Sopenharmony_ci modifiers = mods; 649bf215546Sopenharmony_ci modifiers_count = screen->modifier_props[templ->format].drmFormatModifierCount; 650bf215546Sopenharmony_ci for (unsigned j = 0; j < modifiers_count; j++) 651bf215546Sopenharmony_ci mods[j] = screen->modifier_props[templ->format].pDrmFormatModifierProperties[j].drmFormatModifier; 652bf215546Sopenharmony_ci if (modifiers_count > 1) 653bf215546Sopenharmony_ci try_modifiers = true; 654bf215546Sopenharmony_ci } 655bf215546Sopenharmony_ci const uint64_t *ici_modifiers = winsys_modifier ? &whandle->modifier : modifiers; 656bf215546Sopenharmony_ci unsigned ici_modifier_count = winsys_modifier ? 1 : modifiers_count; 657bf215546Sopenharmony_ci bool success = false; 658bf215546Sopenharmony_ci VkImageCreateInfo ici; 659bf215546Sopenharmony_ci enum pipe_format srgb = PIPE_FORMAT_NONE; 660bf215546Sopenharmony_ci /* We use modifiers as a proxy for "this surface is used as a window system render target". 661bf215546Sopenharmony_ci * For winsys, we need to be able to mutate between srgb and linear, but we don't need general 662bf215546Sopenharmony_ci * image view/shader image format compatibility (that path means losing fast clears or compression on some hardware). 663bf215546Sopenharmony_ci */ 664bf215546Sopenharmony_ci if (ici_modifier_count) { 665bf215546Sopenharmony_ci srgb = util_format_is_srgb(templ->format) ? util_format_linear(templ->format) : util_format_srgb(templ->format); 666bf215546Sopenharmony_ci /* why do these helpers have different default return values? */ 667bf215546Sopenharmony_ci if (srgb == templ->format) 668bf215546Sopenharmony_ci srgb = PIPE_FORMAT_NONE; 669bf215546Sopenharmony_ci } 670bf215546Sopenharmony_ci VkFormat formats[2]; 671bf215546Sopenharmony_ci VkImageFormatListCreateInfo format_list; 672bf215546Sopenharmony_ci if (srgb) { 673bf215546Sopenharmony_ci format_list.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO; 674bf215546Sopenharmony_ci format_list.pNext = NULL; 675bf215546Sopenharmony_ci format_list.viewFormatCount = 2; 676bf215546Sopenharmony_ci format_list.pViewFormats = formats; 677bf215546Sopenharmony_ci 678bf215546Sopenharmony_ci formats[0] = zink_get_format(screen, templ->format); 679bf215546Sopenharmony_ci formats[1] = zink_get_format(screen, srgb); 680bf215546Sopenharmony_ci ici.pNext = &format_list; 681bf215546Sopenharmony_ci } else { 682bf215546Sopenharmony_ci ici.pNext = NULL; 683bf215546Sopenharmony_ci } 684bf215546Sopenharmony_ci uint64_t mod = create_ici(screen, &ici, templ, external == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 685bf215546Sopenharmony_ci templ->bind, ici_modifier_count, ici_modifiers, &success); 686bf215546Sopenharmony_ci VkExternalMemoryImageCreateInfo emici; 687bf215546Sopenharmony_ci VkImageDrmFormatModifierExplicitCreateInfoEXT idfmeci; 688bf215546Sopenharmony_ci VkImageDrmFormatModifierListCreateInfoEXT idfmlci; 689bf215546Sopenharmony_ci VkSubresourceLayout plane_layouts[4]; 690bf215546Sopenharmony_ci VkSubresourceLayout plane_layout = { 691bf215546Sopenharmony_ci .offset = whandle ? whandle->offset : 0, 692bf215546Sopenharmony_ci .size = 0, 693bf215546Sopenharmony_ci .rowPitch = whandle ? whandle->stride : 0, 694bf215546Sopenharmony_ci .arrayPitch = 0, 695bf215546Sopenharmony_ci .depthPitch = 0, 696bf215546Sopenharmony_ci }; 697bf215546Sopenharmony_ci if (!success) 698bf215546Sopenharmony_ci goto fail1; 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci obj->render_target = (ici.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0; 701bf215546Sopenharmony_ci 702bf215546Sopenharmony_ci if (shared || external) { 703bf215546Sopenharmony_ci emici.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; 704bf215546Sopenharmony_ci emici.pNext = ici.pNext; 705bf215546Sopenharmony_ci emici.handleTypes = export_types; 706bf215546Sopenharmony_ci ici.pNext = &emici; 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_ci assert(ici.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT || mod != DRM_FORMAT_MOD_INVALID); 709bf215546Sopenharmony_ci if (whandle && ici.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { 710bf215546Sopenharmony_ci assert(mod == whandle->modifier || !winsys_modifier); 711bf215546Sopenharmony_ci idfmeci.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT; 712bf215546Sopenharmony_ci idfmeci.pNext = ici.pNext; 713bf215546Sopenharmony_ci idfmeci.drmFormatModifier = mod; 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci idfmeci.drmFormatModifierPlaneCount = obj->plane_count; 716bf215546Sopenharmony_ci plane_layouts[0] = plane_layout; 717bf215546Sopenharmony_ci pnext = templ->next; 718bf215546Sopenharmony_ci for (unsigned i = 1; i < obj->plane_count; i++, pnext = pnext->next) { 719bf215546Sopenharmony_ci struct zink_resource *next = zink_resource(pnext); 720bf215546Sopenharmony_ci obj->plane_offsets[i] = plane_layouts[i].offset = next->obj->plane_offsets[i]; 721bf215546Sopenharmony_ci obj->plane_strides[i] = plane_layouts[i].rowPitch = next->obj->plane_strides[i]; 722bf215546Sopenharmony_ci plane_layouts[i].size = 0; 723bf215546Sopenharmony_ci plane_layouts[i].arrayPitch = 0; 724bf215546Sopenharmony_ci plane_layouts[i].depthPitch = 0; 725bf215546Sopenharmony_ci } 726bf215546Sopenharmony_ci idfmeci.pPlaneLayouts = plane_layouts; 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_ci ici.pNext = &idfmeci; 729bf215546Sopenharmony_ci } else if (ici.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { 730bf215546Sopenharmony_ci idfmlci.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT; 731bf215546Sopenharmony_ci idfmlci.pNext = ici.pNext; 732bf215546Sopenharmony_ci idfmlci.drmFormatModifierCount = modifiers_count; 733bf215546Sopenharmony_ci idfmlci.pDrmFormatModifiers = modifiers; 734bf215546Sopenharmony_ci ici.pNext = &idfmlci; 735bf215546Sopenharmony_ci } else if (ici.tiling == VK_IMAGE_TILING_OPTIMAL) { 736bf215546Sopenharmony_ci shared = false; 737bf215546Sopenharmony_ci } 738bf215546Sopenharmony_ci } 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci if (optimal_tiling) 741bf215546Sopenharmony_ci *optimal_tiling = ici.tiling == VK_IMAGE_TILING_OPTIMAL; 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci if (ici.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) 744bf215546Sopenharmony_ci obj->transfer_dst = true; 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci#if defined(ZINK_USE_DMABUF) && !defined(_WIN32) 747bf215546Sopenharmony_ci if (obj->is_aux) { 748bf215546Sopenharmony_ci obj->modifier = mod; 749bf215546Sopenharmony_ci obj->modifier_aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT << whandle->plane; 750bf215546Sopenharmony_ci obj->plane_offsets[whandle->plane] = whandle->offset; 751bf215546Sopenharmony_ci obj->plane_strides[whandle->plane] = whandle->stride; 752bf215546Sopenharmony_ci obj->handle = os_dupfd_cloexec(whandle->handle); 753bf215546Sopenharmony_ci if (obj->handle < 0) { 754bf215546Sopenharmony_ci mesa_loge("ZINK: failed to dup dmabuf fd: %s\n", strerror(errno)); 755bf215546Sopenharmony_ci goto fail1; 756bf215546Sopenharmony_ci } 757bf215546Sopenharmony_ci return obj; 758bf215546Sopenharmony_ci } 759bf215546Sopenharmony_ci#endif 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci VkFormatFeatureFlags feats = 0; 762bf215546Sopenharmony_ci switch (ici.tiling) { 763bf215546Sopenharmony_ci case VK_IMAGE_TILING_LINEAR: 764bf215546Sopenharmony_ci feats = screen->format_props[templ->format].linearTilingFeatures; 765bf215546Sopenharmony_ci break; 766bf215546Sopenharmony_ci case VK_IMAGE_TILING_OPTIMAL: 767bf215546Sopenharmony_ci feats = screen->format_props[templ->format].optimalTilingFeatures; 768bf215546Sopenharmony_ci break; 769bf215546Sopenharmony_ci case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: 770bf215546Sopenharmony_ci feats = VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM; 771bf215546Sopenharmony_ci /* 772bf215546Sopenharmony_ci If is tiling then VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, the value of 773bf215546Sopenharmony_ci imageCreateFormatFeatures is found by calling vkGetPhysicalDeviceFormatProperties2 774bf215546Sopenharmony_ci with VkImageFormatProperties::format equal to VkImageCreateInfo::format and with 775bf215546Sopenharmony_ci VkDrmFormatModifierPropertiesListEXT chained into VkImageFormatProperties2; by 776bf215546Sopenharmony_ci collecting all members of the returned array 777bf215546Sopenharmony_ci VkDrmFormatModifierPropertiesListEXT::pDrmFormatModifierProperties 778bf215546Sopenharmony_ci whose drmFormatModifier belongs to imageCreateDrmFormatModifiers; and by taking the bitwise 779bf215546Sopenharmony_ci intersection, over the collected array members, of drmFormatModifierTilingFeatures. 780bf215546Sopenharmony_ci (The resultant imageCreateFormatFeatures may be empty). 781bf215546Sopenharmony_ci * -Chapter 12. Resource Creation 782bf215546Sopenharmony_ci */ 783bf215546Sopenharmony_ci for (unsigned i = 0; i < screen->modifier_props[templ->format].drmFormatModifierCount; i++) 784bf215546Sopenharmony_ci feats &= screen->modifier_props[templ->format].pDrmFormatModifierProperties[i].drmFormatModifierTilingFeatures; 785bf215546Sopenharmony_ci break; 786bf215546Sopenharmony_ci default: 787bf215546Sopenharmony_ci unreachable("unknown tiling"); 788bf215546Sopenharmony_ci } 789bf215546Sopenharmony_ci obj->vkfeats = feats; 790bf215546Sopenharmony_ci if (util_format_is_yuv(templ->format)) { 791bf215546Sopenharmony_ci if (feats & VK_FORMAT_FEATURE_DISJOINT_BIT) 792bf215546Sopenharmony_ci ici.flags |= VK_IMAGE_CREATE_DISJOINT_BIT; 793bf215546Sopenharmony_ci VkSamplerYcbcrConversionCreateInfo sycci = {0}; 794bf215546Sopenharmony_ci sycci.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO; 795bf215546Sopenharmony_ci sycci.pNext = NULL; 796bf215546Sopenharmony_ci sycci.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; 797bf215546Sopenharmony_ci sycci.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709; 798bf215546Sopenharmony_ci sycci.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; 799bf215546Sopenharmony_ci sycci.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; 800bf215546Sopenharmony_ci sycci.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; 801bf215546Sopenharmony_ci sycci.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; 802bf215546Sopenharmony_ci sycci.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; 803bf215546Sopenharmony_ci if (!feats || (feats & VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) { 804bf215546Sopenharmony_ci sycci.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; 805bf215546Sopenharmony_ci sycci.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; 806bf215546Sopenharmony_ci } else { 807bf215546Sopenharmony_ci assert(feats & VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT); 808bf215546Sopenharmony_ci sycci.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT; 809bf215546Sopenharmony_ci sycci.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT; 810bf215546Sopenharmony_ci } 811bf215546Sopenharmony_ci sycci.chromaFilter = VK_FILTER_LINEAR; 812bf215546Sopenharmony_ci sycci.forceExplicitReconstruction = VK_FALSE; 813bf215546Sopenharmony_ci VkResult res = VKSCR(CreateSamplerYcbcrConversion)(screen->dev, &sycci, NULL, &obj->sampler_conversion); 814bf215546Sopenharmony_ci if (res != VK_SUCCESS) { 815bf215546Sopenharmony_ci mesa_loge("ZINK: vkCreateSamplerYcbcrConversion failed"); 816bf215546Sopenharmony_ci goto fail1; 817bf215546Sopenharmony_ci } 818bf215546Sopenharmony_ci } else if (whandle) { 819bf215546Sopenharmony_ci obj->plane_strides[whandle->plane] = whandle->stride; 820bf215546Sopenharmony_ci } 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci VkResult result = VKSCR(CreateImage)(screen->dev, &ici, NULL, &obj->image); 823bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 824bf215546Sopenharmony_ci if (try_modifiers) { 825bf215546Sopenharmony_ci for (unsigned i = 0; i < modifiers_count; i++) { 826bf215546Sopenharmony_ci if (modifiers[i] == mod) 827bf215546Sopenharmony_ci continue; 828bf215546Sopenharmony_ci idfmeci.drmFormatModifier = modifiers[i]; 829bf215546Sopenharmony_ci result = VKSCR(CreateImage)(screen->dev, &ici, NULL, &obj->image); 830bf215546Sopenharmony_ci if (result == VK_SUCCESS) 831bf215546Sopenharmony_ci break; 832bf215546Sopenharmony_ci } 833bf215546Sopenharmony_ci } 834bf215546Sopenharmony_ci } 835bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 836bf215546Sopenharmony_ci mesa_loge("ZINK: vkCreateImage failed (%s)", vk_Result_to_str(result)); 837bf215546Sopenharmony_ci goto fail1; 838bf215546Sopenharmony_ci } 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci if (ici.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { 841bf215546Sopenharmony_ci VkImageDrmFormatModifierPropertiesEXT modprops = {0}; 842bf215546Sopenharmony_ci modprops.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT; 843bf215546Sopenharmony_ci result = VKSCR(GetImageDrmFormatModifierPropertiesEXT)(screen->dev, obj->image, &modprops); 844bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 845bf215546Sopenharmony_ci mesa_loge("ZINK: vkGetImageDrmFormatModifierPropertiesEXT failed"); 846bf215546Sopenharmony_ci goto fail1; 847bf215546Sopenharmony_ci } 848bf215546Sopenharmony_ci obj->modifier = modprops.drmFormatModifier; 849bf215546Sopenharmony_ci unsigned num_dmabuf_planes = screen->base.get_dmabuf_modifier_planes(&screen->base, obj->modifier, templ->format); 850bf215546Sopenharmony_ci obj->modifier_aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT; 851bf215546Sopenharmony_ci if (num_dmabuf_planes > 1) 852bf215546Sopenharmony_ci obj->modifier_aspect |= VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT; 853bf215546Sopenharmony_ci if (num_dmabuf_planes > 2) 854bf215546Sopenharmony_ci obj->modifier_aspect |= VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT; 855bf215546Sopenharmony_ci if (num_dmabuf_planes > 3) 856bf215546Sopenharmony_ci obj->modifier_aspect |= VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT; 857bf215546Sopenharmony_ci assert(num_dmabuf_planes <= 4); 858bf215546Sopenharmony_ci } 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ci if (VKSCR(GetImageMemoryRequirements2)) { 861bf215546Sopenharmony_ci VkMemoryRequirements2 req2; 862bf215546Sopenharmony_ci req2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; 863bf215546Sopenharmony_ci VkImageMemoryRequirementsInfo2 info2; 864bf215546Sopenharmony_ci info2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2; 865bf215546Sopenharmony_ci info2.pNext = NULL; 866bf215546Sopenharmony_ci info2.image = obj->image; 867bf215546Sopenharmony_ci VkMemoryDedicatedRequirements ded; 868bf215546Sopenharmony_ci ded.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; 869bf215546Sopenharmony_ci ded.pNext = NULL; 870bf215546Sopenharmony_ci req2.pNext = &ded; 871bf215546Sopenharmony_ci VkImagePlaneMemoryRequirementsInfo plane; 872bf215546Sopenharmony_ci plane.sType = VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO; 873bf215546Sopenharmony_ci plane.pNext = NULL; 874bf215546Sopenharmony_ci if (num_planes > 1) 875bf215546Sopenharmony_ci info2.pNext = &plane; 876bf215546Sopenharmony_ci unsigned offset = 0; 877bf215546Sopenharmony_ci for (unsigned i = 0; i < num_planes; i++) { 878bf215546Sopenharmony_ci assert(i < ARRAY_SIZE(plane_aspects)); 879bf215546Sopenharmony_ci plane.planeAspect = plane_aspects[i]; 880bf215546Sopenharmony_ci VKSCR(GetImageMemoryRequirements2)(screen->dev, &info2, &req2); 881bf215546Sopenharmony_ci if (!i) 882bf215546Sopenharmony_ci reqs.alignment = req2.memoryRequirements.alignment; 883bf215546Sopenharmony_ci obj->plane_offsets[i] = offset; 884bf215546Sopenharmony_ci offset += req2.memoryRequirements.size; 885bf215546Sopenharmony_ci reqs.size += req2.memoryRequirements.size; 886bf215546Sopenharmony_ci reqs.memoryTypeBits |= req2.memoryRequirements.memoryTypeBits; 887bf215546Sopenharmony_ci need_dedicated |= ded.prefersDedicatedAllocation || ded.requiresDedicatedAllocation; 888bf215546Sopenharmony_ci } 889bf215546Sopenharmony_ci } else { 890bf215546Sopenharmony_ci VKSCR(GetImageMemoryRequirements)(screen->dev, obj->image, &reqs); 891bf215546Sopenharmony_ci } 892bf215546Sopenharmony_ci if (templ->usage == PIPE_USAGE_STAGING && ici.tiling == VK_IMAGE_TILING_LINEAR) 893bf215546Sopenharmony_ci flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 894bf215546Sopenharmony_ci else 895bf215546Sopenharmony_ci flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_ci obj->vkflags = ici.flags; 898bf215546Sopenharmony_ci obj->vkusage = ici.usage; 899bf215546Sopenharmony_ci } 900bf215546Sopenharmony_ci obj->alignment = reqs.alignment; 901bf215546Sopenharmony_ci 902bf215546Sopenharmony_ci if (templ->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT || templ->usage == PIPE_USAGE_DYNAMIC) 903bf215546Sopenharmony_ci flags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 904bf215546Sopenharmony_ci else if (!(flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) && 905bf215546Sopenharmony_ci templ->usage == PIPE_USAGE_STAGING) 906bf215546Sopenharmony_ci flags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; 907bf215546Sopenharmony_ci 908bf215546Sopenharmony_ci if (templ->bind & ZINK_BIND_TRANSIENT) 909bf215546Sopenharmony_ci flags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; 910bf215546Sopenharmony_ci 911bf215546Sopenharmony_ci VkMemoryAllocateInfo mai; 912bf215546Sopenharmony_ci enum zink_alloc_flag aflags = templ->flags & PIPE_RESOURCE_FLAG_SPARSE ? ZINK_ALLOC_SPARSE : 0; 913bf215546Sopenharmony_ci mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 914bf215546Sopenharmony_ci mai.pNext = NULL; 915bf215546Sopenharmony_ci mai.allocationSize = reqs.size; 916bf215546Sopenharmony_ci enum zink_heap heap = zink_heap_from_domain_flags(flags, aflags); 917bf215546Sopenharmony_ci mai.memoryTypeIndex = screen->heap_map[heap]; 918bf215546Sopenharmony_ci if (unlikely(!(reqs.memoryTypeBits & BITFIELD_BIT(mai.memoryTypeIndex)))) { 919bf215546Sopenharmony_ci /* not valid based on reqs; demote to more compatible type */ 920bf215546Sopenharmony_ci switch (heap) { 921bf215546Sopenharmony_ci case ZINK_HEAP_DEVICE_LOCAL_VISIBLE: 922bf215546Sopenharmony_ci heap = ZINK_HEAP_DEVICE_LOCAL; 923bf215546Sopenharmony_ci break; 924bf215546Sopenharmony_ci case ZINK_HEAP_HOST_VISIBLE_CACHED: 925bf215546Sopenharmony_ci heap = ZINK_HEAP_HOST_VISIBLE_COHERENT; 926bf215546Sopenharmony_ci break; 927bf215546Sopenharmony_ci default: 928bf215546Sopenharmony_ci break; 929bf215546Sopenharmony_ci } 930bf215546Sopenharmony_ci mai.memoryTypeIndex = screen->heap_map[heap]; 931bf215546Sopenharmony_ci assert(reqs.memoryTypeBits & BITFIELD_BIT(mai.memoryTypeIndex)); 932bf215546Sopenharmony_ci } 933bf215546Sopenharmony_ci 934bf215546Sopenharmony_ci VkMemoryDedicatedAllocateInfo ded_alloc_info = { 935bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, 936bf215546Sopenharmony_ci .pNext = mai.pNext, 937bf215546Sopenharmony_ci .image = obj->image, 938bf215546Sopenharmony_ci .buffer = VK_NULL_HANDLE, 939bf215546Sopenharmony_ci }; 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci if (screen->info.have_KHR_dedicated_allocation && need_dedicated) { 942bf215546Sopenharmony_ci ded_alloc_info.pNext = mai.pNext; 943bf215546Sopenharmony_ci mai.pNext = &ded_alloc_info; 944bf215546Sopenharmony_ci } 945bf215546Sopenharmony_ci 946bf215546Sopenharmony_ci VkExportMemoryAllocateInfo emai; 947bf215546Sopenharmony_ci if ((templ->bind & ZINK_BIND_VIDEO) || ((templ->bind & PIPE_BIND_SHARED) && shared) || (templ->bind & ZINK_BIND_DMABUF)) { 948bf215546Sopenharmony_ci emai.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; 949bf215546Sopenharmony_ci emai.handleTypes = export_types; 950bf215546Sopenharmony_ci 951bf215546Sopenharmony_ci emai.pNext = mai.pNext; 952bf215546Sopenharmony_ci mai.pNext = &emai; 953bf215546Sopenharmony_ci obj->exportable = true; 954bf215546Sopenharmony_ci } 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci#ifdef ZINK_USE_DMABUF 957bf215546Sopenharmony_ci 958bf215546Sopenharmony_ci#if !defined(_WIN32) 959bf215546Sopenharmony_ci VkImportMemoryFdInfoKHR imfi = { 960bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, 961bf215546Sopenharmony_ci NULL, 962bf215546Sopenharmony_ci }; 963bf215546Sopenharmony_ci 964bf215546Sopenharmony_ci if (whandle) { 965bf215546Sopenharmony_ci imfi.pNext = NULL; 966bf215546Sopenharmony_ci imfi.handleType = external; 967bf215546Sopenharmony_ci imfi.fd = os_dupfd_cloexec(whandle->handle); 968bf215546Sopenharmony_ci if (imfi.fd < 0) { 969bf215546Sopenharmony_ci mesa_loge("ZINK: failed to dup dmabuf fd: %s\n", strerror(errno)); 970bf215546Sopenharmony_ci goto fail1; 971bf215546Sopenharmony_ci } 972bf215546Sopenharmony_ci 973bf215546Sopenharmony_ci imfi.pNext = mai.pNext; 974bf215546Sopenharmony_ci mai.pNext = &imfi; 975bf215546Sopenharmony_ci } 976bf215546Sopenharmony_ci#else 977bf215546Sopenharmony_ci VkImportMemoryWin32HandleInfoKHR imfi = { 978bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, 979bf215546Sopenharmony_ci NULL, 980bf215546Sopenharmony_ci }; 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_ci if (whandle) { 983bf215546Sopenharmony_ci HANDLE source_target = GetCurrentProcess(); 984bf215546Sopenharmony_ci HANDLE out_handle; 985bf215546Sopenharmony_ci 986bf215546Sopenharmony_ci bool result = DuplicateHandle(source_target, whandle->handle, source_target, &out_handle, 0, false, DUPLICATE_SAME_ACCESS); 987bf215546Sopenharmony_ci 988bf215546Sopenharmony_ci if (!result || !out_handle) { 989bf215546Sopenharmony_ci mesa_loge("ZINK: failed to DuplicateHandle with winerr: %08x\n", (int)GetLastError()); 990bf215546Sopenharmony_ci goto fail1; 991bf215546Sopenharmony_ci } 992bf215546Sopenharmony_ci 993bf215546Sopenharmony_ci imfi.pNext = NULL; 994bf215546Sopenharmony_ci imfi.handleType = external; 995bf215546Sopenharmony_ci imfi.handle = out_handle; 996bf215546Sopenharmony_ci 997bf215546Sopenharmony_ci imfi.pNext = mai.pNext; 998bf215546Sopenharmony_ci mai.pNext = &imfi; 999bf215546Sopenharmony_ci } 1000bf215546Sopenharmony_ci#endif 1001bf215546Sopenharmony_ci 1002bf215546Sopenharmony_ci#endif 1003bf215546Sopenharmony_ci 1004bf215546Sopenharmony_ci unsigned alignment = MAX2(reqs.alignment, 256); 1005bf215546Sopenharmony_ci if (templ->usage == PIPE_USAGE_STAGING && obj->is_buffer) 1006bf215546Sopenharmony_ci alignment = MAX2(alignment, screen->info.props.limits.minMemoryMapAlignment); 1007bf215546Sopenharmony_ci obj->alignment = alignment; 1008bf215546Sopenharmony_ciretry: 1009bf215546Sopenharmony_ci obj->bo = zink_bo(zink_bo_create(screen, reqs.size, alignment, heap, mai.pNext ? ZINK_ALLOC_NO_SUBALLOC : 0, mai.pNext)); 1010bf215546Sopenharmony_ci if (!obj->bo) { 1011bf215546Sopenharmony_ci if (heap == ZINK_HEAP_DEVICE_LOCAL_VISIBLE) { 1012bf215546Sopenharmony_ci if (templ->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT || templ->usage == PIPE_USAGE_DYNAMIC) 1013bf215546Sopenharmony_ci heap = ZINK_HEAP_HOST_VISIBLE_COHERENT; 1014bf215546Sopenharmony_ci else 1015bf215546Sopenharmony_ci heap = ZINK_HEAP_DEVICE_LOCAL; 1016bf215546Sopenharmony_ci goto retry; 1017bf215546Sopenharmony_ci } 1018bf215546Sopenharmony_ci goto fail2; 1019bf215546Sopenharmony_ci } 1020bf215546Sopenharmony_ci if (aflags == ZINK_ALLOC_SPARSE) { 1021bf215546Sopenharmony_ci obj->size = templ->width0; 1022bf215546Sopenharmony_ci } else { 1023bf215546Sopenharmony_ci obj->offset = zink_bo_get_offset(obj->bo); 1024bf215546Sopenharmony_ci obj->size = zink_bo_get_size(obj->bo); 1025bf215546Sopenharmony_ci } 1026bf215546Sopenharmony_ci 1027bf215546Sopenharmony_ci obj->coherent = obj->bo->base.placement & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 1028bf215546Sopenharmony_ci if (!(templ->flags & PIPE_RESOURCE_FLAG_SPARSE)) { 1029bf215546Sopenharmony_ci obj->host_visible = obj->bo->base.placement & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 1030bf215546Sopenharmony_ci } 1031bf215546Sopenharmony_ci 1032bf215546Sopenharmony_ci if (templ->target == PIPE_BUFFER) { 1033bf215546Sopenharmony_ci if (!(templ->flags & PIPE_RESOURCE_FLAG_SPARSE)) { 1034bf215546Sopenharmony_ci if (VKSCR(BindBufferMemory)(screen->dev, obj->buffer, zink_bo_get_mem(obj->bo), obj->offset) != VK_SUCCESS) { 1035bf215546Sopenharmony_ci mesa_loge("ZINK: vkBindBufferMemory failed"); 1036bf215546Sopenharmony_ci goto fail3; 1037bf215546Sopenharmony_ci } 1038bf215546Sopenharmony_ci if (obj->storage_buffer && VKSCR(BindBufferMemory)(screen->dev, obj->storage_buffer, zink_bo_get_mem(obj->bo), obj->offset) != VK_SUCCESS) { 1039bf215546Sopenharmony_ci mesa_loge("ZINK: vkBindBufferMemory failed"); 1040bf215546Sopenharmony_ci goto fail3; 1041bf215546Sopenharmony_ci } 1042bf215546Sopenharmony_ci } 1043bf215546Sopenharmony_ci } else { 1044bf215546Sopenharmony_ci if (num_planes > 1) { 1045bf215546Sopenharmony_ci VkBindImageMemoryInfo infos[3]; 1046bf215546Sopenharmony_ci VkBindImagePlaneMemoryInfo planes[3]; 1047bf215546Sopenharmony_ci for (unsigned i = 0; i < num_planes; i++) { 1048bf215546Sopenharmony_ci infos[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; 1049bf215546Sopenharmony_ci infos[i].image = obj->image; 1050bf215546Sopenharmony_ci infos[i].memory = zink_bo_get_mem(obj->bo); 1051bf215546Sopenharmony_ci infos[i].memoryOffset = obj->plane_offsets[i]; 1052bf215546Sopenharmony_ci if (templ->bind & ZINK_BIND_VIDEO) { 1053bf215546Sopenharmony_ci infos[i].pNext = &planes[i]; 1054bf215546Sopenharmony_ci planes[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO; 1055bf215546Sopenharmony_ci planes[i].pNext = NULL; 1056bf215546Sopenharmony_ci planes[i].planeAspect = plane_aspects[i]; 1057bf215546Sopenharmony_ci } 1058bf215546Sopenharmony_ci } 1059bf215546Sopenharmony_ci if (VKSCR(BindImageMemory2)(screen->dev, num_planes, infos) != VK_SUCCESS) { 1060bf215546Sopenharmony_ci mesa_loge("ZINK: vkBindImageMemory2 failed"); 1061bf215546Sopenharmony_ci goto fail3; 1062bf215546Sopenharmony_ci } 1063bf215546Sopenharmony_ci } else { 1064bf215546Sopenharmony_ci if (!(templ->flags & PIPE_RESOURCE_FLAG_SPARSE)) 1065bf215546Sopenharmony_ci if (VKSCR(BindImageMemory)(screen->dev, obj->image, zink_bo_get_mem(obj->bo), obj->offset) != VK_SUCCESS) { 1066bf215546Sopenharmony_ci mesa_loge("ZINK: vkBindImageMemory failed"); 1067bf215546Sopenharmony_ci goto fail3; 1068bf215546Sopenharmony_ci } 1069bf215546Sopenharmony_ci } 1070bf215546Sopenharmony_ci } 1071bf215546Sopenharmony_ci return obj; 1072bf215546Sopenharmony_ci 1073bf215546Sopenharmony_cifail3: 1074bf215546Sopenharmony_ci zink_bo_unref(screen, obj->bo); 1075bf215546Sopenharmony_ci 1076bf215546Sopenharmony_cifail2: 1077bf215546Sopenharmony_ci if (templ->target == PIPE_BUFFER) { 1078bf215546Sopenharmony_ci VKSCR(DestroyBuffer)(screen->dev, obj->buffer, NULL); 1079bf215546Sopenharmony_ci VKSCR(DestroyBuffer)(screen->dev, obj->storage_buffer, NULL); 1080bf215546Sopenharmony_ci } else 1081bf215546Sopenharmony_ci VKSCR(DestroyImage)(screen->dev, obj->image, NULL); 1082bf215546Sopenharmony_cifail1: 1083bf215546Sopenharmony_ci FREE(obj); 1084bf215546Sopenharmony_ci return NULL; 1085bf215546Sopenharmony_ci} 1086bf215546Sopenharmony_ci 1087bf215546Sopenharmony_cistatic struct pipe_resource * 1088bf215546Sopenharmony_ciresource_create(struct pipe_screen *pscreen, 1089bf215546Sopenharmony_ci const struct pipe_resource *templ, 1090bf215546Sopenharmony_ci struct winsys_handle *whandle, 1091bf215546Sopenharmony_ci unsigned external_usage, 1092bf215546Sopenharmony_ci const uint64_t *modifiers, int modifiers_count, 1093bf215546Sopenharmony_ci const void *loader_private) 1094bf215546Sopenharmony_ci{ 1095bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pscreen); 1096bf215546Sopenharmony_ci struct zink_resource *res = CALLOC_STRUCT_CL(zink_resource); 1097bf215546Sopenharmony_ci 1098bf215546Sopenharmony_ci if (modifiers_count > 0 && screen->info.have_EXT_image_drm_format_modifier) { 1099bf215546Sopenharmony_ci /* for rebinds */ 1100bf215546Sopenharmony_ci res->modifiers_count = modifiers_count; 1101bf215546Sopenharmony_ci res->modifiers = mem_dup(modifiers, modifiers_count * sizeof(uint64_t)); 1102bf215546Sopenharmony_ci if (!res->modifiers) { 1103bf215546Sopenharmony_ci FREE_CL(res); 1104bf215546Sopenharmony_ci return NULL; 1105bf215546Sopenharmony_ci } 1106bf215546Sopenharmony_ci } 1107bf215546Sopenharmony_ci 1108bf215546Sopenharmony_ci res->base.b = *templ; 1109bf215546Sopenharmony_ci 1110bf215546Sopenharmony_ci threaded_resource_init(&res->base.b, false); 1111bf215546Sopenharmony_ci pipe_reference_init(&res->base.b.reference, 1); 1112bf215546Sopenharmony_ci res->base.b.screen = pscreen; 1113bf215546Sopenharmony_ci 1114bf215546Sopenharmony_ci bool optimal_tiling = false; 1115bf215546Sopenharmony_ci struct pipe_resource templ2 = *templ; 1116bf215546Sopenharmony_ci if (templ2.flags & PIPE_RESOURCE_FLAG_SPARSE) 1117bf215546Sopenharmony_ci templ2.bind |= PIPE_BIND_SHADER_IMAGE; 1118bf215546Sopenharmony_ci if (screen->faked_e5sparse && templ->format == PIPE_FORMAT_R9G9B9E5_FLOAT) { 1119bf215546Sopenharmony_ci templ2.flags &= ~PIPE_RESOURCE_FLAG_SPARSE; 1120bf215546Sopenharmony_ci res->base.b.flags &= ~PIPE_RESOURCE_FLAG_SPARSE; 1121bf215546Sopenharmony_ci } 1122bf215546Sopenharmony_ci res->obj = resource_object_create(screen, &templ2, whandle, &optimal_tiling, modifiers, modifiers_count, loader_private); 1123bf215546Sopenharmony_ci if (!res->obj) { 1124bf215546Sopenharmony_ci free(res->modifiers); 1125bf215546Sopenharmony_ci FREE_CL(res); 1126bf215546Sopenharmony_ci return NULL; 1127bf215546Sopenharmony_ci } 1128bf215546Sopenharmony_ci 1129bf215546Sopenharmony_ci res->internal_format = templ->format; 1130bf215546Sopenharmony_ci if (templ->target == PIPE_BUFFER) { 1131bf215546Sopenharmony_ci util_range_init(&res->valid_buffer_range); 1132bf215546Sopenharmony_ci res->base.b.bind |= PIPE_BIND_SHADER_IMAGE; 1133bf215546Sopenharmony_ci if (!screen->resizable_bar && templ->width0 >= 8196) { 1134bf215546Sopenharmony_ci /* We don't want to evict buffers from VRAM by mapping them for CPU access, 1135bf215546Sopenharmony_ci * because they might never be moved back again. If a buffer is large enough, 1136bf215546Sopenharmony_ci * upload data by copying from a temporary GTT buffer. 8K might not seem much, 1137bf215546Sopenharmony_ci * but there can be 100000 buffers. 1138bf215546Sopenharmony_ci * 1139bf215546Sopenharmony_ci * This tweak improves performance for viewperf. 1140bf215546Sopenharmony_ci */ 1141bf215546Sopenharmony_ci res->base.b.flags |= PIPE_RESOURCE_FLAG_DONT_MAP_DIRECTLY; 1142bf215546Sopenharmony_ci } 1143bf215546Sopenharmony_ci } else { 1144bf215546Sopenharmony_ci if (templ->flags & PIPE_RESOURCE_FLAG_SPARSE) 1145bf215546Sopenharmony_ci res->base.b.bind |= PIPE_BIND_SHADER_IMAGE; 1146bf215546Sopenharmony_ci if (templ->flags & PIPE_RESOURCE_FLAG_SPARSE) { 1147bf215546Sopenharmony_ci uint32_t count = 1; 1148bf215546Sopenharmony_ci VKSCR(GetImageSparseMemoryRequirements)(screen->dev, res->obj->image, &count, &res->sparse); 1149bf215546Sopenharmony_ci res->base.b.nr_sparse_levels = res->sparse.imageMipTailFirstLod; 1150bf215546Sopenharmony_ci } 1151bf215546Sopenharmony_ci res->format = zink_get_format(screen, templ->format); 1152bf215546Sopenharmony_ci if (templ->target == PIPE_TEXTURE_1D || templ->target == PIPE_TEXTURE_1D_ARRAY) { 1153bf215546Sopenharmony_ci res->need_2D = (screen->need_2D_zs && util_format_is_depth_or_stencil(templ->format)) || 1154bf215546Sopenharmony_ci (screen->need_2D_sparse && (templ->flags & PIPE_RESOURCE_FLAG_SPARSE)); 1155bf215546Sopenharmony_ci } 1156bf215546Sopenharmony_ci res->dmabuf_acquire = whandle && whandle->type == WINSYS_HANDLE_TYPE_FD; 1157bf215546Sopenharmony_ci res->dmabuf = res->dmabuf_acquire = whandle && whandle->type == WINSYS_HANDLE_TYPE_FD; 1158bf215546Sopenharmony_ci res->layout = res->dmabuf_acquire ? VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED; 1159bf215546Sopenharmony_ci res->optimal_tiling = optimal_tiling; 1160bf215546Sopenharmony_ci res->aspect = aspect_from_format(templ->format); 1161bf215546Sopenharmony_ci } 1162bf215546Sopenharmony_ci 1163bf215546Sopenharmony_ci if (loader_private) { 1164bf215546Sopenharmony_ci if (templ->bind & PIPE_BIND_DISPLAY_TARGET) { 1165bf215546Sopenharmony_ci /* backbuffer */ 1166bf215546Sopenharmony_ci res->obj->dt = zink_kopper_displaytarget_create(screen, 1167bf215546Sopenharmony_ci res->base.b.bind, 1168bf215546Sopenharmony_ci res->base.b.format, 1169bf215546Sopenharmony_ci templ->width0, 1170bf215546Sopenharmony_ci templ->height0, 1171bf215546Sopenharmony_ci 64, loader_private, 1172bf215546Sopenharmony_ci &res->dt_stride); 1173bf215546Sopenharmony_ci assert(res->obj->dt); 1174bf215546Sopenharmony_ci } else { 1175bf215546Sopenharmony_ci /* frontbuffer */ 1176bf215546Sopenharmony_ci struct zink_resource *back = (void*)loader_private; 1177bf215546Sopenharmony_ci struct kopper_displaytarget *cdt = back->obj->dt; 1178bf215546Sopenharmony_ci cdt->refcount++; 1179bf215546Sopenharmony_ci assert(back->obj->dt); 1180bf215546Sopenharmony_ci res->obj->dt = back->obj->dt; 1181bf215546Sopenharmony_ci } 1182bf215546Sopenharmony_ci struct kopper_displaytarget *cdt = res->obj->dt; 1183bf215546Sopenharmony_ci if (zink_kopper_has_srgb(cdt)) 1184bf215546Sopenharmony_ci res->obj->vkflags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; 1185bf215546Sopenharmony_ci if (cdt->swapchain->scci.flags == VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) 1186bf215546Sopenharmony_ci res->obj->vkflags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; 1187bf215546Sopenharmony_ci res->obj->vkusage = cdt->swapchain->scci.imageUsage; 1188bf215546Sopenharmony_ci res->base.b.bind |= PIPE_BIND_DISPLAY_TARGET; 1189bf215546Sopenharmony_ci res->optimal_tiling = true; 1190bf215546Sopenharmony_ci res->swapchain = true; 1191bf215546Sopenharmony_ci } 1192bf215546Sopenharmony_ci if (!res->obj->host_visible) 1193bf215546Sopenharmony_ci res->base.b.flags |= PIPE_RESOURCE_FLAG_DONT_MAP_DIRECTLY; 1194bf215546Sopenharmony_ci if (res->obj->is_buffer) { 1195bf215546Sopenharmony_ci res->base.buffer_id_unique = util_idalloc_mt_alloc(&screen->buffer_ids); 1196bf215546Sopenharmony_ci _mesa_hash_table_init(&res->bufferview_cache, NULL, NULL, equals_bvci); 1197bf215546Sopenharmony_ci simple_mtx_init(&res->bufferview_mtx, mtx_plain); 1198bf215546Sopenharmony_ci } else { 1199bf215546Sopenharmony_ci _mesa_hash_table_init(&res->surface_cache, NULL, NULL, equals_ivci); 1200bf215546Sopenharmony_ci simple_mtx_init(&res->surface_mtx, mtx_plain); 1201bf215546Sopenharmony_ci } 1202bf215546Sopenharmony_ci if (res->obj->exportable) 1203bf215546Sopenharmony_ci res->base.b.bind |= ZINK_BIND_DMABUF; 1204bf215546Sopenharmony_ci return &res->base.b; 1205bf215546Sopenharmony_ci} 1206bf215546Sopenharmony_ci 1207bf215546Sopenharmony_cistatic struct pipe_resource * 1208bf215546Sopenharmony_cizink_resource_create(struct pipe_screen *pscreen, 1209bf215546Sopenharmony_ci const struct pipe_resource *templ) 1210bf215546Sopenharmony_ci{ 1211bf215546Sopenharmony_ci return resource_create(pscreen, templ, NULL, 0, NULL, 0, NULL); 1212bf215546Sopenharmony_ci} 1213bf215546Sopenharmony_ci 1214bf215546Sopenharmony_cistatic struct pipe_resource * 1215bf215546Sopenharmony_cizink_resource_create_with_modifiers(struct pipe_screen *pscreen, const struct pipe_resource *templ, 1216bf215546Sopenharmony_ci const uint64_t *modifiers, int modifiers_count) 1217bf215546Sopenharmony_ci{ 1218bf215546Sopenharmony_ci return resource_create(pscreen, templ, NULL, 0, modifiers, modifiers_count, NULL); 1219bf215546Sopenharmony_ci} 1220bf215546Sopenharmony_ci 1221bf215546Sopenharmony_cistatic struct pipe_resource * 1222bf215546Sopenharmony_cizink_resource_create_drawable(struct pipe_screen *pscreen, 1223bf215546Sopenharmony_ci const struct pipe_resource *templ, 1224bf215546Sopenharmony_ci const void *loader_private) 1225bf215546Sopenharmony_ci{ 1226bf215546Sopenharmony_ci return resource_create(pscreen, templ, NULL, 0, NULL, 0, loader_private); 1227bf215546Sopenharmony_ci} 1228bf215546Sopenharmony_ci 1229bf215546Sopenharmony_cistatic bool 1230bf215546Sopenharmony_ciadd_resource_bind(struct zink_context *ctx, struct zink_resource *res, unsigned bind) 1231bf215546Sopenharmony_ci{ 1232bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 1233bf215546Sopenharmony_ci assert((res->base.b.bind & bind) == 0); 1234bf215546Sopenharmony_ci zink_resource_image_barrier(ctx, res, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0, 0); 1235bf215546Sopenharmony_ci res->base.b.bind |= bind; 1236bf215546Sopenharmony_ci struct zink_resource_object *old_obj = res->obj; 1237bf215546Sopenharmony_ci if (bind & ZINK_BIND_DMABUF && !res->modifiers_count && screen->info.have_EXT_image_drm_format_modifier) { 1238bf215546Sopenharmony_ci res->modifiers_count = screen->modifier_props[res->base.b.format].drmFormatModifierCount; 1239bf215546Sopenharmony_ci res->modifiers = malloc(res->modifiers_count * sizeof(uint64_t)); 1240bf215546Sopenharmony_ci for (unsigned i = 0; i < screen->modifier_props[res->base.b.format].drmFormatModifierCount; i++) 1241bf215546Sopenharmony_ci res->modifiers[i] = screen->modifier_props[res->base.b.format].pDrmFormatModifierProperties[i].drmFormatModifier; 1242bf215546Sopenharmony_ci } 1243bf215546Sopenharmony_ci struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, &res->optimal_tiling, res->modifiers, res->modifiers_count, NULL); 1244bf215546Sopenharmony_ci if (!new_obj) { 1245bf215546Sopenharmony_ci debug_printf("new backing resource alloc failed!"); 1246bf215546Sopenharmony_ci res->base.b.bind &= ~bind; 1247bf215546Sopenharmony_ci return false; 1248bf215546Sopenharmony_ci } 1249bf215546Sopenharmony_ci struct zink_resource staging = *res; 1250bf215546Sopenharmony_ci staging.obj = old_obj; 1251bf215546Sopenharmony_ci staging.all_binds = 0; 1252bf215546Sopenharmony_ci res->layout = VK_IMAGE_LAYOUT_UNDEFINED; 1253bf215546Sopenharmony_ci res->obj->access = 0; 1254bf215546Sopenharmony_ci res->obj->access_stage = 0; 1255bf215546Sopenharmony_ci bool needs_unref = true; 1256bf215546Sopenharmony_ci if (zink_resource_has_usage(res)) { 1257bf215546Sopenharmony_ci zink_batch_reference_resource_move(&ctx->batch, res); 1258bf215546Sopenharmony_ci needs_unref = false; 1259bf215546Sopenharmony_ci } 1260bf215546Sopenharmony_ci res->obj = new_obj; 1261bf215546Sopenharmony_ci zink_descriptor_set_refs_clear(&old_obj->desc_set_refs, old_obj); 1262bf215546Sopenharmony_ci for (unsigned i = 0; i <= res->base.b.last_level; i++) { 1263bf215546Sopenharmony_ci struct pipe_box box = {0, 0, 0, 1264bf215546Sopenharmony_ci u_minify(res->base.b.width0, i), 1265bf215546Sopenharmony_ci u_minify(res->base.b.height0, i), res->base.b.array_size}; 1266bf215546Sopenharmony_ci box.depth = util_num_layers(&res->base.b, i); 1267bf215546Sopenharmony_ci ctx->base.resource_copy_region(&ctx->base, &res->base.b, i, 0, 0, 0, &staging.base.b, i, &box); 1268bf215546Sopenharmony_ci } 1269bf215546Sopenharmony_ci if (needs_unref) 1270bf215546Sopenharmony_ci zink_resource_object_reference(screen, &old_obj, NULL); 1271bf215546Sopenharmony_ci return true; 1272bf215546Sopenharmony_ci} 1273bf215546Sopenharmony_ci 1274bf215546Sopenharmony_cistatic bool 1275bf215546Sopenharmony_cizink_resource_get_param(struct pipe_screen *pscreen, struct pipe_context *pctx, 1276bf215546Sopenharmony_ci struct pipe_resource *pres, 1277bf215546Sopenharmony_ci unsigned plane, 1278bf215546Sopenharmony_ci unsigned layer, 1279bf215546Sopenharmony_ci unsigned level, 1280bf215546Sopenharmony_ci enum pipe_resource_param param, 1281bf215546Sopenharmony_ci unsigned handle_usage, 1282bf215546Sopenharmony_ci uint64_t *value) 1283bf215546Sopenharmony_ci{ 1284bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pscreen); 1285bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 1286bf215546Sopenharmony_ci struct zink_resource_object *obj = res->obj; 1287bf215546Sopenharmony_ci struct winsys_handle whandle; 1288bf215546Sopenharmony_ci VkImageAspectFlags aspect; 1289bf215546Sopenharmony_ci if (obj->modifier_aspect) { 1290bf215546Sopenharmony_ci switch (plane) { 1291bf215546Sopenharmony_ci case 0: 1292bf215546Sopenharmony_ci aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT; 1293bf215546Sopenharmony_ci break; 1294bf215546Sopenharmony_ci case 1: 1295bf215546Sopenharmony_ci aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT; 1296bf215546Sopenharmony_ci break; 1297bf215546Sopenharmony_ci case 2: 1298bf215546Sopenharmony_ci aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT; 1299bf215546Sopenharmony_ci break; 1300bf215546Sopenharmony_ci case 3: 1301bf215546Sopenharmony_ci aspect = VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT; 1302bf215546Sopenharmony_ci break; 1303bf215546Sopenharmony_ci default: 1304bf215546Sopenharmony_ci unreachable("how many planes you got in this thing?"); 1305bf215546Sopenharmony_ci } 1306bf215546Sopenharmony_ci } else if (res->obj->sampler_conversion) { 1307bf215546Sopenharmony_ci aspect = VK_IMAGE_ASPECT_PLANE_0_BIT; 1308bf215546Sopenharmony_ci } else { 1309bf215546Sopenharmony_ci aspect = res->aspect; 1310bf215546Sopenharmony_ci } 1311bf215546Sopenharmony_ci switch (param) { 1312bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_NPLANES: 1313bf215546Sopenharmony_ci if (screen->info.have_EXT_image_drm_format_modifier) 1314bf215546Sopenharmony_ci *value = util_format_get_num_planes(res->drm_format); 1315bf215546Sopenharmony_ci else 1316bf215546Sopenharmony_ci *value = 1; 1317bf215546Sopenharmony_ci break; 1318bf215546Sopenharmony_ci 1319bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_STRIDE: { 1320bf215546Sopenharmony_ci VkImageSubresource sub_res = {0}; 1321bf215546Sopenharmony_ci VkSubresourceLayout sub_res_layout = {0}; 1322bf215546Sopenharmony_ci 1323bf215546Sopenharmony_ci sub_res.aspectMask = aspect; 1324bf215546Sopenharmony_ci 1325bf215546Sopenharmony_ci VKSCR(GetImageSubresourceLayout)(screen->dev, obj->image, &sub_res, &sub_res_layout); 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_ci *value = sub_res_layout.rowPitch; 1328bf215546Sopenharmony_ci break; 1329bf215546Sopenharmony_ci } 1330bf215546Sopenharmony_ci 1331bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_OFFSET: { 1332bf215546Sopenharmony_ci VkImageSubresource isr = { 1333bf215546Sopenharmony_ci aspect, 1334bf215546Sopenharmony_ci level, 1335bf215546Sopenharmony_ci layer 1336bf215546Sopenharmony_ci }; 1337bf215546Sopenharmony_ci VkSubresourceLayout srl; 1338bf215546Sopenharmony_ci VKSCR(GetImageSubresourceLayout)(screen->dev, obj->image, &isr, &srl); 1339bf215546Sopenharmony_ci *value = srl.offset; 1340bf215546Sopenharmony_ci break; 1341bf215546Sopenharmony_ci } 1342bf215546Sopenharmony_ci 1343bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_MODIFIER: { 1344bf215546Sopenharmony_ci *value = obj->modifier; 1345bf215546Sopenharmony_ci break; 1346bf215546Sopenharmony_ci } 1347bf215546Sopenharmony_ci 1348bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_LAYER_STRIDE: { 1349bf215546Sopenharmony_ci VkImageSubresource isr = { 1350bf215546Sopenharmony_ci aspect, 1351bf215546Sopenharmony_ci level, 1352bf215546Sopenharmony_ci layer 1353bf215546Sopenharmony_ci }; 1354bf215546Sopenharmony_ci VkSubresourceLayout srl; 1355bf215546Sopenharmony_ci VKSCR(GetImageSubresourceLayout)(screen->dev, obj->image, &isr, &srl); 1356bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_3D) 1357bf215546Sopenharmony_ci *value = srl.depthPitch; 1358bf215546Sopenharmony_ci else 1359bf215546Sopenharmony_ci *value = srl.arrayPitch; 1360bf215546Sopenharmony_ci break; 1361bf215546Sopenharmony_ci } 1362bf215546Sopenharmony_ci 1363bf215546Sopenharmony_ci return false; 1364bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS: 1365bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED: 1366bf215546Sopenharmony_ci case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD: { 1367bf215546Sopenharmony_ci#ifdef ZINK_USE_DMABUF 1368bf215546Sopenharmony_ci memset(&whandle, 0, sizeof(whandle)); 1369bf215546Sopenharmony_ci if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED) 1370bf215546Sopenharmony_ci whandle.type = WINSYS_HANDLE_TYPE_SHARED; 1371bf215546Sopenharmony_ci if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS) 1372bf215546Sopenharmony_ci whandle.type = WINSYS_HANDLE_TYPE_KMS; 1373bf215546Sopenharmony_ci else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD) 1374bf215546Sopenharmony_ci whandle.type = WINSYS_HANDLE_TYPE_FD; 1375bf215546Sopenharmony_ci 1376bf215546Sopenharmony_ci if (!pscreen->resource_get_handle(pscreen, pctx, pres, &whandle, handle_usage)) 1377bf215546Sopenharmony_ci return false; 1378bf215546Sopenharmony_ci 1379bf215546Sopenharmony_ci#ifdef _WIN32 1380bf215546Sopenharmony_ci *value = (uintptr_t)whandle.handle; 1381bf215546Sopenharmony_ci#else 1382bf215546Sopenharmony_ci *value = whandle.handle; 1383bf215546Sopenharmony_ci#endif 1384bf215546Sopenharmony_ci break; 1385bf215546Sopenharmony_ci#else 1386bf215546Sopenharmony_ci (void)whandle; 1387bf215546Sopenharmony_ci return false; 1388bf215546Sopenharmony_ci#endif 1389bf215546Sopenharmony_ci } 1390bf215546Sopenharmony_ci } 1391bf215546Sopenharmony_ci return true; 1392bf215546Sopenharmony_ci} 1393bf215546Sopenharmony_ci 1394bf215546Sopenharmony_cistatic bool 1395bf215546Sopenharmony_cizink_resource_get_handle(struct pipe_screen *pscreen, 1396bf215546Sopenharmony_ci struct pipe_context *context, 1397bf215546Sopenharmony_ci struct pipe_resource *tex, 1398bf215546Sopenharmony_ci struct winsys_handle *whandle, 1399bf215546Sopenharmony_ci unsigned usage) 1400bf215546Sopenharmony_ci{ 1401bf215546Sopenharmony_ci if (whandle->type == WINSYS_HANDLE_TYPE_FD || whandle->type == WINSYS_HANDLE_TYPE_KMS) { 1402bf215546Sopenharmony_ci#ifdef ZINK_USE_DMABUF 1403bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(tex); 1404bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pscreen); 1405bf215546Sopenharmony_ci struct zink_resource_object *obj = res->obj; 1406bf215546Sopenharmony_ci 1407bf215546Sopenharmony_ci#if !defined(_WIN32) 1408bf215546Sopenharmony_ci if (whandle->type == WINSYS_HANDLE_TYPE_KMS && screen->drm_fd == -1) { 1409bf215546Sopenharmony_ci whandle->handle = -1; 1410bf215546Sopenharmony_ci } else { 1411bf215546Sopenharmony_ci if (!res->obj->exportable) { 1412bf215546Sopenharmony_ci assert(!res->all_binds); //TODO handle if problematic 1413bf215546Sopenharmony_ci assert(!zink_resource_usage_is_unflushed(res)); 1414bf215546Sopenharmony_ci unsigned bind = ZINK_BIND_DMABUF; 1415bf215546Sopenharmony_ci if (!(res->base.b.bind & PIPE_BIND_SHARED)) 1416bf215546Sopenharmony_ci bind |= PIPE_BIND_SHARED; 1417bf215546Sopenharmony_ci if (!add_resource_bind(screen->copy_context, res, bind)) 1418bf215546Sopenharmony_ci return false; 1419bf215546Sopenharmony_ci p_atomic_inc(&screen->image_rebind_counter); 1420bf215546Sopenharmony_ci screen->copy_context->base.flush(&screen->copy_context->base, NULL, 0); 1421bf215546Sopenharmony_ci obj = res->obj; 1422bf215546Sopenharmony_ci } 1423bf215546Sopenharmony_ci 1424bf215546Sopenharmony_ci VkMemoryGetFdInfoKHR fd_info = {0}; 1425bf215546Sopenharmony_ci int fd; 1426bf215546Sopenharmony_ci fd_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR; 1427bf215546Sopenharmony_ci fd_info.memory = zink_bo_get_mem(obj->bo); 1428bf215546Sopenharmony_ci if (whandle->type == WINSYS_HANDLE_TYPE_FD) 1429bf215546Sopenharmony_ci fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 1430bf215546Sopenharmony_ci else 1431bf215546Sopenharmony_ci fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; 1432bf215546Sopenharmony_ci VkResult result = VKSCR(GetMemoryFdKHR)(screen->dev, &fd_info, &fd); 1433bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1434bf215546Sopenharmony_ci mesa_loge("ZINK: vkGetMemoryFdKHR failed"); 1435bf215546Sopenharmony_ci return false; 1436bf215546Sopenharmony_ci } 1437bf215546Sopenharmony_ci if (whandle->type == WINSYS_HANDLE_TYPE_KMS) { 1438bf215546Sopenharmony_ci uint32_t h; 1439bf215546Sopenharmony_ci bool ret = zink_bo_get_kms_handle(screen, obj->bo, fd, &h); 1440bf215546Sopenharmony_ci close(fd); 1441bf215546Sopenharmony_ci if (!ret) 1442bf215546Sopenharmony_ci return false; 1443bf215546Sopenharmony_ci fd = h; 1444bf215546Sopenharmony_ci } 1445bf215546Sopenharmony_ci 1446bf215546Sopenharmony_ci whandle->handle = fd; 1447bf215546Sopenharmony_ci } 1448bf215546Sopenharmony_ci#else 1449bf215546Sopenharmony_ci VkMemoryGetWin32HandleInfoKHR handle_info = {0}; 1450bf215546Sopenharmony_ci HANDLE handle; 1451bf215546Sopenharmony_ci handle_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR; 1452bf215546Sopenharmony_ci //TODO: remove for wsi 1453bf215546Sopenharmony_ci handle_info.memory = zink_bo_get_mem(obj->bo); 1454bf215546Sopenharmony_ci handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; 1455bf215546Sopenharmony_ci VkResult result = VKSCR(GetMemoryWin32HandleKHR)(screen->dev, &handle_info, &handle); 1456bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1457bf215546Sopenharmony_ci return false; 1458bf215546Sopenharmony_ci whandle->handle = handle; 1459bf215546Sopenharmony_ci#endif 1460bf215546Sopenharmony_ci uint64_t value; 1461bf215546Sopenharmony_ci zink_resource_get_param(pscreen, context, tex, 0, 0, 0, PIPE_RESOURCE_PARAM_MODIFIER, 0, &value); 1462bf215546Sopenharmony_ci whandle->modifier = value; 1463bf215546Sopenharmony_ci zink_resource_get_param(pscreen, context, tex, 0, 0, 0, PIPE_RESOURCE_PARAM_OFFSET, 0, &value); 1464bf215546Sopenharmony_ci whandle->offset = value; 1465bf215546Sopenharmony_ci zink_resource_get_param(pscreen, context, tex, 0, 0, 0, PIPE_RESOURCE_PARAM_STRIDE, 0, &value); 1466bf215546Sopenharmony_ci whandle->stride = value; 1467bf215546Sopenharmony_ci#else 1468bf215546Sopenharmony_ci return false; 1469bf215546Sopenharmony_ci#endif 1470bf215546Sopenharmony_ci } 1471bf215546Sopenharmony_ci return true; 1472bf215546Sopenharmony_ci} 1473bf215546Sopenharmony_ci 1474bf215546Sopenharmony_cistatic struct pipe_resource * 1475bf215546Sopenharmony_cizink_resource_from_handle(struct pipe_screen *pscreen, 1476bf215546Sopenharmony_ci const struct pipe_resource *templ, 1477bf215546Sopenharmony_ci struct winsys_handle *whandle, 1478bf215546Sopenharmony_ci unsigned usage) 1479bf215546Sopenharmony_ci{ 1480bf215546Sopenharmony_ci#ifdef ZINK_USE_DMABUF 1481bf215546Sopenharmony_ci if (whandle->modifier != DRM_FORMAT_MOD_INVALID && 1482bf215546Sopenharmony_ci !zink_screen(pscreen)->info.have_EXT_image_drm_format_modifier) 1483bf215546Sopenharmony_ci return NULL; 1484bf215546Sopenharmony_ci 1485bf215546Sopenharmony_ci struct pipe_resource templ2 = *templ; 1486bf215546Sopenharmony_ci if (templ->format == PIPE_FORMAT_NONE) 1487bf215546Sopenharmony_ci templ2.format = whandle->format; 1488bf215546Sopenharmony_ci 1489bf215546Sopenharmony_ci uint64_t modifier = DRM_FORMAT_MOD_INVALID; 1490bf215546Sopenharmony_ci int modifier_count = 0; 1491bf215546Sopenharmony_ci if (whandle->modifier != DRM_FORMAT_MOD_INVALID) { 1492bf215546Sopenharmony_ci modifier = whandle->modifier; 1493bf215546Sopenharmony_ci modifier_count = 1; 1494bf215546Sopenharmony_ci } 1495bf215546Sopenharmony_ci struct pipe_resource *pres = resource_create(pscreen, &templ2, whandle, usage, &modifier, modifier_count, NULL); 1496bf215546Sopenharmony_ci if (pres) { 1497bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 1498bf215546Sopenharmony_ci res->drm_format = whandle->format; 1499bf215546Sopenharmony_ci if (pres->target != PIPE_BUFFER) 1500bf215546Sopenharmony_ci res->valid = true; 1501bf215546Sopenharmony_ci } 1502bf215546Sopenharmony_ci return pres; 1503bf215546Sopenharmony_ci#else 1504bf215546Sopenharmony_ci return NULL; 1505bf215546Sopenharmony_ci#endif 1506bf215546Sopenharmony_ci} 1507bf215546Sopenharmony_ci 1508bf215546Sopenharmony_cistruct zink_memory_object { 1509bf215546Sopenharmony_ci struct pipe_memory_object b; 1510bf215546Sopenharmony_ci struct winsys_handle whandle; 1511bf215546Sopenharmony_ci}; 1512bf215546Sopenharmony_ci 1513bf215546Sopenharmony_cistatic struct pipe_memory_object * 1514bf215546Sopenharmony_cizink_memobj_create_from_handle(struct pipe_screen *pscreen, struct winsys_handle *whandle, bool dedicated) 1515bf215546Sopenharmony_ci{ 1516bf215546Sopenharmony_ci struct zink_memory_object *memobj = CALLOC_STRUCT(zink_memory_object); 1517bf215546Sopenharmony_ci if (!memobj) 1518bf215546Sopenharmony_ci return NULL; 1519bf215546Sopenharmony_ci memcpy(&memobj->whandle, whandle, sizeof(struct winsys_handle)); 1520bf215546Sopenharmony_ci memobj->whandle.type = ZINK_EXTERNAL_MEMORY_HANDLE; 1521bf215546Sopenharmony_ci 1522bf215546Sopenharmony_ci#ifdef ZINK_USE_DMABUF 1523bf215546Sopenharmony_ci 1524bf215546Sopenharmony_ci#if !defined(_WIN32) 1525bf215546Sopenharmony_ci memobj->whandle.handle = os_dupfd_cloexec(whandle->handle); 1526bf215546Sopenharmony_ci#else 1527bf215546Sopenharmony_ci HANDLE source_target = GetCurrentProcess(); 1528bf215546Sopenharmony_ci HANDLE out_handle; 1529bf215546Sopenharmony_ci 1530bf215546Sopenharmony_ci DuplicateHandle(source_target, whandle->handle, source_target, &out_handle, 0, false, DUPLICATE_SAME_ACCESS); 1531bf215546Sopenharmony_ci memobj->whandle.handle = out_handle; 1532bf215546Sopenharmony_ci 1533bf215546Sopenharmony_ci#endif /* _WIN32 */ 1534bf215546Sopenharmony_ci#endif /* ZINK_USE_DMABUF */ 1535bf215546Sopenharmony_ci 1536bf215546Sopenharmony_ci return (struct pipe_memory_object *)memobj; 1537bf215546Sopenharmony_ci} 1538bf215546Sopenharmony_ci 1539bf215546Sopenharmony_cistatic void 1540bf215546Sopenharmony_cizink_memobj_destroy(struct pipe_screen *pscreen, struct pipe_memory_object *pmemobj) 1541bf215546Sopenharmony_ci{ 1542bf215546Sopenharmony_ci#ifdef ZINK_USE_DMABUF 1543bf215546Sopenharmony_ci struct zink_memory_object *memobj = (struct zink_memory_object *)pmemobj; 1544bf215546Sopenharmony_ci 1545bf215546Sopenharmony_ci#if !defined(_WIN32) 1546bf215546Sopenharmony_ci close(memobj->whandle.handle); 1547bf215546Sopenharmony_ci#else 1548bf215546Sopenharmony_ci CloseHandle(memobj->whandle.handle); 1549bf215546Sopenharmony_ci#endif /* _WIN32 */ 1550bf215546Sopenharmony_ci#endif /* ZINK_USE_DMABUF */ 1551bf215546Sopenharmony_ci 1552bf215546Sopenharmony_ci FREE(pmemobj); 1553bf215546Sopenharmony_ci} 1554bf215546Sopenharmony_ci 1555bf215546Sopenharmony_cistatic struct pipe_resource * 1556bf215546Sopenharmony_cizink_resource_from_memobj(struct pipe_screen *pscreen, 1557bf215546Sopenharmony_ci const struct pipe_resource *templ, 1558bf215546Sopenharmony_ci struct pipe_memory_object *pmemobj, 1559bf215546Sopenharmony_ci uint64_t offset) 1560bf215546Sopenharmony_ci{ 1561bf215546Sopenharmony_ci struct zink_memory_object *memobj = (struct zink_memory_object *)pmemobj; 1562bf215546Sopenharmony_ci 1563bf215546Sopenharmony_ci struct pipe_resource *pres = resource_create(pscreen, templ, &memobj->whandle, 0, NULL, 0, NULL); 1564bf215546Sopenharmony_ci if (pres && pres->target != PIPE_BUFFER) 1565bf215546Sopenharmony_ci zink_resource(pres)->valid = true; 1566bf215546Sopenharmony_ci return pres; 1567bf215546Sopenharmony_ci} 1568bf215546Sopenharmony_ci 1569bf215546Sopenharmony_cistatic bool 1570bf215546Sopenharmony_ciinvalidate_buffer(struct zink_context *ctx, struct zink_resource *res) 1571bf215546Sopenharmony_ci{ 1572bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 1573bf215546Sopenharmony_ci 1574bf215546Sopenharmony_ci assert(res->base.b.target == PIPE_BUFFER); 1575bf215546Sopenharmony_ci 1576bf215546Sopenharmony_ci if (res->base.b.flags & PIPE_RESOURCE_FLAG_SPARSE) 1577bf215546Sopenharmony_ci return false; 1578bf215546Sopenharmony_ci 1579bf215546Sopenharmony_ci if (res->valid_buffer_range.start > res->valid_buffer_range.end) 1580bf215546Sopenharmony_ci return false; 1581bf215546Sopenharmony_ci 1582bf215546Sopenharmony_ci if (res->so_valid) 1583bf215546Sopenharmony_ci ctx->dirty_so_targets = true; 1584bf215546Sopenharmony_ci /* force counter buffer reset */ 1585bf215546Sopenharmony_ci res->so_valid = false; 1586bf215546Sopenharmony_ci 1587bf215546Sopenharmony_ci util_range_set_empty(&res->valid_buffer_range); 1588bf215546Sopenharmony_ci if (!zink_resource_has_usage(res)) 1589bf215546Sopenharmony_ci return false; 1590bf215546Sopenharmony_ci 1591bf215546Sopenharmony_ci struct zink_resource_object *old_obj = res->obj; 1592bf215546Sopenharmony_ci struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, NULL, NULL, 0, NULL); 1593bf215546Sopenharmony_ci if (!new_obj) { 1594bf215546Sopenharmony_ci debug_printf("new backing resource alloc failed!"); 1595bf215546Sopenharmony_ci return false; 1596bf215546Sopenharmony_ci } 1597bf215546Sopenharmony_ci /* this ref must be transferred before rebind or else BOOM */ 1598bf215546Sopenharmony_ci zink_batch_reference_resource_move(&ctx->batch, res); 1599bf215546Sopenharmony_ci res->obj = new_obj; 1600bf215546Sopenharmony_ci zink_resource_rebind(ctx, res); 1601bf215546Sopenharmony_ci zink_descriptor_set_refs_clear(&old_obj->desc_set_refs, old_obj); 1602bf215546Sopenharmony_ci return true; 1603bf215546Sopenharmony_ci} 1604bf215546Sopenharmony_ci 1605bf215546Sopenharmony_ci 1606bf215546Sopenharmony_cistatic void 1607bf215546Sopenharmony_cizink_resource_invalidate(struct pipe_context *pctx, struct pipe_resource *pres) 1608bf215546Sopenharmony_ci{ 1609bf215546Sopenharmony_ci if (pres->target == PIPE_BUFFER) 1610bf215546Sopenharmony_ci invalidate_buffer(zink_context(pctx), zink_resource(pres)); 1611bf215546Sopenharmony_ci else { 1612bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 1613bf215546Sopenharmony_ci if (res->valid && res->fb_binds) 1614bf215546Sopenharmony_ci zink_context(pctx)->rp_loadop_changed = true; 1615bf215546Sopenharmony_ci res->valid = false; 1616bf215546Sopenharmony_ci } 1617bf215546Sopenharmony_ci} 1618bf215546Sopenharmony_ci 1619bf215546Sopenharmony_cistatic void 1620bf215546Sopenharmony_cizink_transfer_copy_bufimage(struct zink_context *ctx, 1621bf215546Sopenharmony_ci struct zink_resource *dst, 1622bf215546Sopenharmony_ci struct zink_resource *src, 1623bf215546Sopenharmony_ci struct zink_transfer *trans) 1624bf215546Sopenharmony_ci{ 1625bf215546Sopenharmony_ci assert((trans->base.b.usage & (PIPE_MAP_DEPTH_ONLY | PIPE_MAP_STENCIL_ONLY)) != 1626bf215546Sopenharmony_ci (PIPE_MAP_DEPTH_ONLY | PIPE_MAP_STENCIL_ONLY)); 1627bf215546Sopenharmony_ci 1628bf215546Sopenharmony_ci bool buf2img = src->base.b.target == PIPE_BUFFER; 1629bf215546Sopenharmony_ci 1630bf215546Sopenharmony_ci struct pipe_box box = trans->base.b.box; 1631bf215546Sopenharmony_ci int x = box.x; 1632bf215546Sopenharmony_ci if (buf2img) 1633bf215546Sopenharmony_ci box.x = trans->offset; 1634bf215546Sopenharmony_ci 1635bf215546Sopenharmony_ci if (dst->obj->transfer_dst) 1636bf215546Sopenharmony_ci zink_copy_image_buffer(ctx, dst, src, trans->base.b.level, buf2img ? x : 0, 1637bf215546Sopenharmony_ci box.y, box.z, trans->base.b.level, &box, trans->base.b.usage); 1638bf215546Sopenharmony_ci else 1639bf215546Sopenharmony_ci util_blitter_copy_texture(ctx->blitter, &dst->base.b, trans->base.b.level, 1640bf215546Sopenharmony_ci x, box.y, box.z, &src->base.b, 1641bf215546Sopenharmony_ci 0, &box); 1642bf215546Sopenharmony_ci} 1643bf215546Sopenharmony_ci 1644bf215546Sopenharmony_ciALWAYS_INLINE static void 1645bf215546Sopenharmony_cialign_offset_size(const VkDeviceSize alignment, VkDeviceSize *offset, VkDeviceSize *size, VkDeviceSize obj_size) 1646bf215546Sopenharmony_ci{ 1647bf215546Sopenharmony_ci VkDeviceSize align = *offset % alignment; 1648bf215546Sopenharmony_ci if (alignment - 1 > *offset) 1649bf215546Sopenharmony_ci *offset = 0; 1650bf215546Sopenharmony_ci else 1651bf215546Sopenharmony_ci *offset -= align, *size += align; 1652bf215546Sopenharmony_ci align = alignment - (*size % alignment); 1653bf215546Sopenharmony_ci if (*offset + *size + align > obj_size) 1654bf215546Sopenharmony_ci *size = obj_size - *offset; 1655bf215546Sopenharmony_ci else 1656bf215546Sopenharmony_ci *size += align; 1657bf215546Sopenharmony_ci} 1658bf215546Sopenharmony_ci 1659bf215546Sopenharmony_ciVkMappedMemoryRange 1660bf215546Sopenharmony_cizink_resource_init_mem_range(struct zink_screen *screen, struct zink_resource_object *obj, VkDeviceSize offset, VkDeviceSize size) 1661bf215546Sopenharmony_ci{ 1662bf215546Sopenharmony_ci assert(obj->size); 1663bf215546Sopenharmony_ci align_offset_size(screen->info.props.limits.nonCoherentAtomSize, &offset, &size, obj->size); 1664bf215546Sopenharmony_ci VkMappedMemoryRange range = { 1665bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 1666bf215546Sopenharmony_ci NULL, 1667bf215546Sopenharmony_ci zink_bo_get_mem(obj->bo), 1668bf215546Sopenharmony_ci offset, 1669bf215546Sopenharmony_ci size 1670bf215546Sopenharmony_ci }; 1671bf215546Sopenharmony_ci assert(range.size); 1672bf215546Sopenharmony_ci return range; 1673bf215546Sopenharmony_ci} 1674bf215546Sopenharmony_ci 1675bf215546Sopenharmony_cistatic void * 1676bf215546Sopenharmony_cimap_resource(struct zink_screen *screen, struct zink_resource *res) 1677bf215546Sopenharmony_ci{ 1678bf215546Sopenharmony_ci assert(res->obj->host_visible); 1679bf215546Sopenharmony_ci return zink_bo_map(screen, res->obj->bo); 1680bf215546Sopenharmony_ci} 1681bf215546Sopenharmony_ci 1682bf215546Sopenharmony_cistatic void 1683bf215546Sopenharmony_ciunmap_resource(struct zink_screen *screen, struct zink_resource *res) 1684bf215546Sopenharmony_ci{ 1685bf215546Sopenharmony_ci zink_bo_unmap(screen, res->obj->bo); 1686bf215546Sopenharmony_ci} 1687bf215546Sopenharmony_ci 1688bf215546Sopenharmony_cistatic struct zink_transfer * 1689bf215546Sopenharmony_cicreate_transfer(struct zink_context *ctx, struct pipe_resource *pres, unsigned usage, const struct pipe_box *box) 1690bf215546Sopenharmony_ci{ 1691bf215546Sopenharmony_ci struct zink_transfer *trans; 1692bf215546Sopenharmony_ci 1693bf215546Sopenharmony_ci if (usage & PIPE_MAP_THREAD_SAFE) 1694bf215546Sopenharmony_ci trans = calloc(1, sizeof(*trans)); 1695bf215546Sopenharmony_ci else if (usage & TC_TRANSFER_MAP_THREADED_UNSYNC) 1696bf215546Sopenharmony_ci trans = slab_zalloc(&ctx->transfer_pool_unsync); 1697bf215546Sopenharmony_ci else 1698bf215546Sopenharmony_ci trans = slab_zalloc(&ctx->transfer_pool); 1699bf215546Sopenharmony_ci if (!trans) 1700bf215546Sopenharmony_ci return NULL; 1701bf215546Sopenharmony_ci 1702bf215546Sopenharmony_ci pipe_resource_reference(&trans->base.b.resource, pres); 1703bf215546Sopenharmony_ci 1704bf215546Sopenharmony_ci trans->base.b.usage = usage; 1705bf215546Sopenharmony_ci trans->base.b.box = *box; 1706bf215546Sopenharmony_ci return trans; 1707bf215546Sopenharmony_ci} 1708bf215546Sopenharmony_ci 1709bf215546Sopenharmony_cistatic void 1710bf215546Sopenharmony_cidestroy_transfer(struct zink_context *ctx, struct zink_transfer *trans) 1711bf215546Sopenharmony_ci{ 1712bf215546Sopenharmony_ci if (trans->base.b.usage & PIPE_MAP_THREAD_SAFE) { 1713bf215546Sopenharmony_ci free(trans); 1714bf215546Sopenharmony_ci } else { 1715bf215546Sopenharmony_ci /* Don't use pool_transfers_unsync. We are always in the driver 1716bf215546Sopenharmony_ci * thread. Freeing an object into a different pool is allowed. 1717bf215546Sopenharmony_ci */ 1718bf215546Sopenharmony_ci slab_free(&ctx->transfer_pool, trans); 1719bf215546Sopenharmony_ci } 1720bf215546Sopenharmony_ci} 1721bf215546Sopenharmony_ci 1722bf215546Sopenharmony_cistatic void * 1723bf215546Sopenharmony_cizink_buffer_map(struct pipe_context *pctx, 1724bf215546Sopenharmony_ci struct pipe_resource *pres, 1725bf215546Sopenharmony_ci unsigned level, 1726bf215546Sopenharmony_ci unsigned usage, 1727bf215546Sopenharmony_ci const struct pipe_box *box, 1728bf215546Sopenharmony_ci struct pipe_transfer **transfer) 1729bf215546Sopenharmony_ci{ 1730bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 1731bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pctx->screen); 1732bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 1733bf215546Sopenharmony_ci struct zink_transfer *trans = create_transfer(ctx, pres, usage, box); 1734bf215546Sopenharmony_ci if (!trans) 1735bf215546Sopenharmony_ci return NULL; 1736bf215546Sopenharmony_ci 1737bf215546Sopenharmony_ci void *ptr = NULL; 1738bf215546Sopenharmony_ci 1739bf215546Sopenharmony_ci if (res->base.is_user_ptr) 1740bf215546Sopenharmony_ci usage |= PIPE_MAP_PERSISTENT; 1741bf215546Sopenharmony_ci 1742bf215546Sopenharmony_ci /* See if the buffer range being mapped has never been initialized, 1743bf215546Sopenharmony_ci * in which case it can be mapped unsynchronized. */ 1744bf215546Sopenharmony_ci if (!(usage & (PIPE_MAP_UNSYNCHRONIZED | TC_TRANSFER_MAP_NO_INFER_UNSYNCHRONIZED)) && 1745bf215546Sopenharmony_ci usage & PIPE_MAP_WRITE && !res->base.is_shared && 1746bf215546Sopenharmony_ci !util_ranges_intersect(&res->valid_buffer_range, box->x, box->x + box->width)) { 1747bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 1748bf215546Sopenharmony_ci } 1749bf215546Sopenharmony_ci 1750bf215546Sopenharmony_ci /* If discarding the entire range, discard the whole resource instead. */ 1751bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_RANGE && box->x == 0 && box->width == res->base.b.width0) { 1752bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE; 1753bf215546Sopenharmony_ci } 1754bf215546Sopenharmony_ci 1755bf215546Sopenharmony_ci /* If a buffer in VRAM is too large and the range is discarded, don't 1756bf215546Sopenharmony_ci * map it directly. This makes sure that the buffer stays in VRAM. 1757bf215546Sopenharmony_ci */ 1758bf215546Sopenharmony_ci bool force_discard_range = false; 1759bf215546Sopenharmony_ci if (usage & (PIPE_MAP_DISCARD_WHOLE_RESOURCE | PIPE_MAP_DISCARD_RANGE) && 1760bf215546Sopenharmony_ci !(usage & PIPE_MAP_PERSISTENT) && 1761bf215546Sopenharmony_ci res->base.b.flags & PIPE_RESOURCE_FLAG_DONT_MAP_DIRECTLY) { 1762bf215546Sopenharmony_ci usage &= ~(PIPE_MAP_DISCARD_WHOLE_RESOURCE | PIPE_MAP_UNSYNCHRONIZED); 1763bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_RANGE; 1764bf215546Sopenharmony_ci force_discard_range = true; 1765bf215546Sopenharmony_ci } 1766bf215546Sopenharmony_ci 1767bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE && 1768bf215546Sopenharmony_ci !(usage & (PIPE_MAP_UNSYNCHRONIZED | TC_TRANSFER_MAP_NO_INVALIDATE))) { 1769bf215546Sopenharmony_ci assert(usage & PIPE_MAP_WRITE); 1770bf215546Sopenharmony_ci 1771bf215546Sopenharmony_ci if (invalidate_buffer(ctx, res)) { 1772bf215546Sopenharmony_ci /* At this point, the buffer is always idle. */ 1773bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 1774bf215546Sopenharmony_ci } else { 1775bf215546Sopenharmony_ci /* Fall back to a temporary buffer. */ 1776bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_RANGE; 1777bf215546Sopenharmony_ci } 1778bf215546Sopenharmony_ci } 1779bf215546Sopenharmony_ci 1780bf215546Sopenharmony_ci unsigned map_offset = box->x; 1781bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_RANGE && 1782bf215546Sopenharmony_ci (!res->obj->host_visible || 1783bf215546Sopenharmony_ci !(usage & (PIPE_MAP_UNSYNCHRONIZED | PIPE_MAP_PERSISTENT)))) { 1784bf215546Sopenharmony_ci 1785bf215546Sopenharmony_ci /* Check if mapping this buffer would cause waiting for the GPU. 1786bf215546Sopenharmony_ci */ 1787bf215546Sopenharmony_ci 1788bf215546Sopenharmony_ci if (!res->obj->host_visible || force_discard_range || 1789bf215546Sopenharmony_ci !zink_resource_usage_check_completion(screen, res, ZINK_RESOURCE_ACCESS_RW)) { 1790bf215546Sopenharmony_ci /* Do a wait-free write-only transfer using a temporary buffer. */ 1791bf215546Sopenharmony_ci unsigned offset; 1792bf215546Sopenharmony_ci 1793bf215546Sopenharmony_ci /* If we are not called from the driver thread, we have 1794bf215546Sopenharmony_ci * to use the uploader from u_threaded_context, which is 1795bf215546Sopenharmony_ci * local to the calling thread. 1796bf215546Sopenharmony_ci */ 1797bf215546Sopenharmony_ci struct u_upload_mgr *mgr; 1798bf215546Sopenharmony_ci if (usage & TC_TRANSFER_MAP_THREADED_UNSYNC) 1799bf215546Sopenharmony_ci mgr = ctx->tc->base.stream_uploader; 1800bf215546Sopenharmony_ci else 1801bf215546Sopenharmony_ci mgr = ctx->base.stream_uploader; 1802bf215546Sopenharmony_ci u_upload_alloc(mgr, 0, box->width, 1803bf215546Sopenharmony_ci screen->info.props.limits.minMemoryMapAlignment, &offset, 1804bf215546Sopenharmony_ci (struct pipe_resource **)&trans->staging_res, (void **)&ptr); 1805bf215546Sopenharmony_ci res = zink_resource(trans->staging_res); 1806bf215546Sopenharmony_ci trans->offset = offset; 1807bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 1808bf215546Sopenharmony_ci ptr = ((uint8_t *)ptr); 1809bf215546Sopenharmony_ci } else { 1810bf215546Sopenharmony_ci /* At this point, the buffer is always idle (we checked it above). */ 1811bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 1812bf215546Sopenharmony_ci } 1813bf215546Sopenharmony_ci } else if (usage & PIPE_MAP_DONTBLOCK) { 1814bf215546Sopenharmony_ci /* sparse/device-local will always need to wait since it has to copy */ 1815bf215546Sopenharmony_ci if (!res->obj->host_visible) 1816bf215546Sopenharmony_ci goto success; 1817bf215546Sopenharmony_ci if (!zink_resource_usage_check_completion(screen, res, ZINK_RESOURCE_ACCESS_WRITE)) 1818bf215546Sopenharmony_ci goto success; 1819bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 1820bf215546Sopenharmony_ci } else if (!(usage & PIPE_MAP_UNSYNCHRONIZED) && 1821bf215546Sopenharmony_ci (((usage & PIPE_MAP_READ) && !(usage & PIPE_MAP_PERSISTENT) && res->base.b.usage != PIPE_USAGE_STAGING) || !res->obj->host_visible)) { 1822bf215546Sopenharmony_ci assert(!(usage & (TC_TRANSFER_MAP_THREADED_UNSYNC | PIPE_MAP_THREAD_SAFE))); 1823bf215546Sopenharmony_ci if (!res->obj->host_visible || !(usage & PIPE_MAP_ONCE)) { 1824bf215546Sopenharmony_ci trans->offset = box->x % screen->info.props.limits.minMemoryMapAlignment; 1825bf215546Sopenharmony_ci trans->staging_res = pipe_buffer_create(&screen->base, PIPE_BIND_LINEAR, PIPE_USAGE_STAGING, box->width + trans->offset); 1826bf215546Sopenharmony_ci if (!trans->staging_res) 1827bf215546Sopenharmony_ci goto fail; 1828bf215546Sopenharmony_ci struct zink_resource *staging_res = zink_resource(trans->staging_res); 1829bf215546Sopenharmony_ci zink_copy_buffer(ctx, staging_res, res, trans->offset, box->x, box->width); 1830bf215546Sopenharmony_ci res = staging_res; 1831bf215546Sopenharmony_ci usage &= ~PIPE_MAP_UNSYNCHRONIZED; 1832bf215546Sopenharmony_ci map_offset = trans->offset; 1833bf215546Sopenharmony_ci } 1834bf215546Sopenharmony_ci } else if ((usage & PIPE_MAP_UNSYNCHRONIZED) && !res->obj->host_visible) { 1835bf215546Sopenharmony_ci trans->offset = box->x % screen->info.props.limits.minMemoryMapAlignment; 1836bf215546Sopenharmony_ci trans->staging_res = pipe_buffer_create(&screen->base, PIPE_BIND_LINEAR, PIPE_USAGE_STAGING, box->width + trans->offset); 1837bf215546Sopenharmony_ci if (!trans->staging_res) 1838bf215546Sopenharmony_ci goto fail; 1839bf215546Sopenharmony_ci struct zink_resource *staging_res = zink_resource(trans->staging_res); 1840bf215546Sopenharmony_ci res = staging_res; 1841bf215546Sopenharmony_ci map_offset = trans->offset; 1842bf215546Sopenharmony_ci } 1843bf215546Sopenharmony_ci 1844bf215546Sopenharmony_ci if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) { 1845bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) 1846bf215546Sopenharmony_ci zink_resource_usage_wait(ctx, res, ZINK_RESOURCE_ACCESS_RW); 1847bf215546Sopenharmony_ci else 1848bf215546Sopenharmony_ci zink_resource_usage_wait(ctx, res, ZINK_RESOURCE_ACCESS_WRITE); 1849bf215546Sopenharmony_ci res->obj->access = 0; 1850bf215546Sopenharmony_ci res->obj->access_stage = 0; 1851bf215546Sopenharmony_ci } 1852bf215546Sopenharmony_ci 1853bf215546Sopenharmony_ci if (!ptr) { 1854bf215546Sopenharmony_ci /* if writing to a streamout buffer, ensure synchronization next time it's used */ 1855bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE && res->so_valid) { 1856bf215546Sopenharmony_ci ctx->dirty_so_targets = true; 1857bf215546Sopenharmony_ci /* force counter buffer reset */ 1858bf215546Sopenharmony_ci res->so_valid = false; 1859bf215546Sopenharmony_ci } 1860bf215546Sopenharmony_ci ptr = map_resource(screen, res); 1861bf215546Sopenharmony_ci if (!ptr) 1862bf215546Sopenharmony_ci goto fail; 1863bf215546Sopenharmony_ci ptr = ((uint8_t *)ptr) + map_offset; 1864bf215546Sopenharmony_ci } 1865bf215546Sopenharmony_ci 1866bf215546Sopenharmony_ci if (!res->obj->coherent 1867bf215546Sopenharmony_ci#if defined(MVK_VERSION) 1868bf215546Sopenharmony_ci // Work around for MoltenVk limitation specifically on coherent memory 1869bf215546Sopenharmony_ci // MoltenVk returns blank memory ranges when there should be data present 1870bf215546Sopenharmony_ci // This is a known limitation of MoltenVK. 1871bf215546Sopenharmony_ci // See https://github.com/KhronosGroup/MoltenVK/blob/master/Docs/MoltenVK_Runtime_UserGuide.md#known-moltenvk-limitations 1872bf215546Sopenharmony_ci 1873bf215546Sopenharmony_ci || screen->instance_info.have_MVK_moltenvk 1874bf215546Sopenharmony_ci#endif 1875bf215546Sopenharmony_ci ) { 1876bf215546Sopenharmony_ci VkDeviceSize size = box->width; 1877bf215546Sopenharmony_ci VkDeviceSize offset = res->obj->offset + trans->offset; 1878bf215546Sopenharmony_ci VkMappedMemoryRange range = zink_resource_init_mem_range(screen, res->obj, offset, size); 1879bf215546Sopenharmony_ci if (VKSCR(InvalidateMappedMemoryRanges)(screen->dev, 1, &range) != VK_SUCCESS) { 1880bf215546Sopenharmony_ci mesa_loge("ZINK: vkInvalidateMappedMemoryRanges failed"); 1881bf215546Sopenharmony_ci zink_bo_unmap(screen, res->obj->bo); 1882bf215546Sopenharmony_ci goto fail; 1883bf215546Sopenharmony_ci } 1884bf215546Sopenharmony_ci } 1885bf215546Sopenharmony_ci trans->base.b.usage = usage; 1886bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) 1887bf215546Sopenharmony_ci util_range_add(&res->base.b, &res->valid_buffer_range, box->x, box->x + box->width); 1888bf215546Sopenharmony_ci if ((usage & PIPE_MAP_PERSISTENT) && !(usage & PIPE_MAP_COHERENT)) 1889bf215546Sopenharmony_ci res->obj->persistent_maps++; 1890bf215546Sopenharmony_ci 1891bf215546Sopenharmony_cisuccess: 1892bf215546Sopenharmony_ci *transfer = &trans->base.b; 1893bf215546Sopenharmony_ci return ptr; 1894bf215546Sopenharmony_ci 1895bf215546Sopenharmony_cifail: 1896bf215546Sopenharmony_ci destroy_transfer(ctx, trans); 1897bf215546Sopenharmony_ci return NULL; 1898bf215546Sopenharmony_ci} 1899bf215546Sopenharmony_ci 1900bf215546Sopenharmony_cistatic void * 1901bf215546Sopenharmony_cizink_image_map(struct pipe_context *pctx, 1902bf215546Sopenharmony_ci struct pipe_resource *pres, 1903bf215546Sopenharmony_ci unsigned level, 1904bf215546Sopenharmony_ci unsigned usage, 1905bf215546Sopenharmony_ci const struct pipe_box *box, 1906bf215546Sopenharmony_ci struct pipe_transfer **transfer) 1907bf215546Sopenharmony_ci{ 1908bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 1909bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pctx->screen); 1910bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 1911bf215546Sopenharmony_ci struct zink_transfer *trans = create_transfer(ctx, pres, usage, box); 1912bf215546Sopenharmony_ci if (!trans) 1913bf215546Sopenharmony_ci return NULL; 1914bf215546Sopenharmony_ci 1915bf215546Sopenharmony_ci trans->base.b.level = level; 1916bf215546Sopenharmony_ci if (zink_is_swapchain(res)) 1917bf215546Sopenharmony_ci /* this is probably a multi-chain which has already been acquired */ 1918bf215546Sopenharmony_ci zink_kopper_acquire(ctx, res, 0); 1919bf215546Sopenharmony_ci 1920bf215546Sopenharmony_ci void *ptr; 1921bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE && !(usage & PIPE_MAP_READ)) 1922bf215546Sopenharmony_ci /* this is like a blit, so we can potentially dump some clears or maybe we have to */ 1923bf215546Sopenharmony_ci zink_fb_clears_apply_or_discard(ctx, pres, zink_rect_from_box(box), false); 1924bf215546Sopenharmony_ci else if (usage & PIPE_MAP_READ) 1925bf215546Sopenharmony_ci /* if the map region intersects with any clears then we have to apply them */ 1926bf215546Sopenharmony_ci zink_fb_clears_apply_region(ctx, pres, zink_rect_from_box(box)); 1927bf215546Sopenharmony_ci if (res->optimal_tiling || !res->obj->host_visible) { 1928bf215546Sopenharmony_ci enum pipe_format format = pres->format; 1929bf215546Sopenharmony_ci if (usage & PIPE_MAP_DEPTH_ONLY) 1930bf215546Sopenharmony_ci format = util_format_get_depth_only(pres->format); 1931bf215546Sopenharmony_ci else if (usage & PIPE_MAP_STENCIL_ONLY) 1932bf215546Sopenharmony_ci format = PIPE_FORMAT_S8_UINT; 1933bf215546Sopenharmony_ci trans->base.b.stride = util_format_get_stride(format, box->width); 1934bf215546Sopenharmony_ci trans->base.b.layer_stride = util_format_get_2d_size(format, 1935bf215546Sopenharmony_ci trans->base.b.stride, 1936bf215546Sopenharmony_ci box->height); 1937bf215546Sopenharmony_ci 1938bf215546Sopenharmony_ci struct pipe_resource templ = *pres; 1939bf215546Sopenharmony_ci templ.next = NULL; 1940bf215546Sopenharmony_ci templ.format = format; 1941bf215546Sopenharmony_ci templ.usage = usage & PIPE_MAP_READ ? PIPE_USAGE_STAGING : PIPE_USAGE_STREAM; 1942bf215546Sopenharmony_ci templ.target = PIPE_BUFFER; 1943bf215546Sopenharmony_ci templ.bind = PIPE_BIND_LINEAR; 1944bf215546Sopenharmony_ci templ.width0 = trans->base.b.layer_stride * box->depth; 1945bf215546Sopenharmony_ci templ.height0 = templ.depth0 = 0; 1946bf215546Sopenharmony_ci templ.last_level = 0; 1947bf215546Sopenharmony_ci templ.array_size = 1; 1948bf215546Sopenharmony_ci templ.flags = 0; 1949bf215546Sopenharmony_ci 1950bf215546Sopenharmony_ci trans->staging_res = zink_resource_create(pctx->screen, &templ); 1951bf215546Sopenharmony_ci if (!trans->staging_res) 1952bf215546Sopenharmony_ci goto fail; 1953bf215546Sopenharmony_ci 1954bf215546Sopenharmony_ci struct zink_resource *staging_res = zink_resource(trans->staging_res); 1955bf215546Sopenharmony_ci 1956bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) { 1957bf215546Sopenharmony_ci /* force multi-context sync */ 1958bf215546Sopenharmony_ci if (zink_resource_usage_is_unflushed_write(res)) 1959bf215546Sopenharmony_ci zink_resource_usage_wait(ctx, res, ZINK_RESOURCE_ACCESS_WRITE); 1960bf215546Sopenharmony_ci zink_transfer_copy_bufimage(ctx, staging_res, res, trans); 1961bf215546Sopenharmony_ci /* need to wait for rendering to finish */ 1962bf215546Sopenharmony_ci zink_fence_wait(pctx); 1963bf215546Sopenharmony_ci } 1964bf215546Sopenharmony_ci 1965bf215546Sopenharmony_ci ptr = map_resource(screen, staging_res); 1966bf215546Sopenharmony_ci } else { 1967bf215546Sopenharmony_ci assert(!res->optimal_tiling); 1968bf215546Sopenharmony_ci ptr = map_resource(screen, res); 1969bf215546Sopenharmony_ci if (!ptr) 1970bf215546Sopenharmony_ci goto fail; 1971bf215546Sopenharmony_ci if (zink_resource_has_usage(res)) { 1972bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) 1973bf215546Sopenharmony_ci zink_fence_wait(pctx); 1974bf215546Sopenharmony_ci else 1975bf215546Sopenharmony_ci zink_resource_usage_wait(ctx, res, ZINK_RESOURCE_ACCESS_WRITE); 1976bf215546Sopenharmony_ci } 1977bf215546Sopenharmony_ci VkImageSubresource isr = { 1978bf215546Sopenharmony_ci res->modifiers ? res->obj->modifier_aspect : res->aspect, 1979bf215546Sopenharmony_ci level, 1980bf215546Sopenharmony_ci 0 1981bf215546Sopenharmony_ci }; 1982bf215546Sopenharmony_ci VkSubresourceLayout srl; 1983bf215546Sopenharmony_ci VKSCR(GetImageSubresourceLayout)(screen->dev, res->obj->image, &isr, &srl); 1984bf215546Sopenharmony_ci trans->base.b.stride = srl.rowPitch; 1985bf215546Sopenharmony_ci if (res->base.b.target == PIPE_TEXTURE_3D) 1986bf215546Sopenharmony_ci trans->base.b.layer_stride = srl.depthPitch; 1987bf215546Sopenharmony_ci else 1988bf215546Sopenharmony_ci trans->base.b.layer_stride = srl.arrayPitch; 1989bf215546Sopenharmony_ci trans->offset = srl.offset; 1990bf215546Sopenharmony_ci trans->depthPitch = srl.depthPitch; 1991bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(res->base.b.format); 1992bf215546Sopenharmony_ci unsigned offset = srl.offset + 1993bf215546Sopenharmony_ci box->z * srl.depthPitch + 1994bf215546Sopenharmony_ci (box->y / desc->block.height) * srl.rowPitch + 1995bf215546Sopenharmony_ci (box->x / desc->block.width) * (desc->block.bits / 8); 1996bf215546Sopenharmony_ci if (!res->obj->coherent) { 1997bf215546Sopenharmony_ci VkDeviceSize size = (VkDeviceSize)box->width * box->height * desc->block.bits / 8; 1998bf215546Sopenharmony_ci VkMappedMemoryRange range = zink_resource_init_mem_range(screen, res->obj, res->obj->offset + offset, size); 1999bf215546Sopenharmony_ci if (VKSCR(FlushMappedMemoryRanges)(screen->dev, 1, &range) != VK_SUCCESS) { 2000bf215546Sopenharmony_ci mesa_loge("ZINK: vkFlushMappedMemoryRanges failed"); 2001bf215546Sopenharmony_ci } 2002bf215546Sopenharmony_ci } 2003bf215546Sopenharmony_ci ptr = ((uint8_t *)ptr) + offset; 2004bf215546Sopenharmony_ci } 2005bf215546Sopenharmony_ci if (!ptr) 2006bf215546Sopenharmony_ci goto fail; 2007bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) { 2008bf215546Sopenharmony_ci if (!res->valid && res->fb_binds) 2009bf215546Sopenharmony_ci ctx->rp_loadop_changed = true; 2010bf215546Sopenharmony_ci res->valid = true; 2011bf215546Sopenharmony_ci } 2012bf215546Sopenharmony_ci 2013bf215546Sopenharmony_ci if (sizeof(void*) == 4) 2014bf215546Sopenharmony_ci trans->base.b.usage |= ZINK_MAP_TEMPORARY; 2015bf215546Sopenharmony_ci if ((usage & PIPE_MAP_PERSISTENT) && !(usage & PIPE_MAP_COHERENT)) 2016bf215546Sopenharmony_ci res->obj->persistent_maps++; 2017bf215546Sopenharmony_ci 2018bf215546Sopenharmony_ci *transfer = &trans->base.b; 2019bf215546Sopenharmony_ci return ptr; 2020bf215546Sopenharmony_ci 2021bf215546Sopenharmony_cifail: 2022bf215546Sopenharmony_ci destroy_transfer(ctx, trans); 2023bf215546Sopenharmony_ci return NULL; 2024bf215546Sopenharmony_ci} 2025bf215546Sopenharmony_ci 2026bf215546Sopenharmony_cistatic void 2027bf215546Sopenharmony_cizink_transfer_flush_region(struct pipe_context *pctx, 2028bf215546Sopenharmony_ci struct pipe_transfer *ptrans, 2029bf215546Sopenharmony_ci const struct pipe_box *box) 2030bf215546Sopenharmony_ci{ 2031bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 2032bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(ptrans->resource); 2033bf215546Sopenharmony_ci struct zink_transfer *trans = (struct zink_transfer *)ptrans; 2034bf215546Sopenharmony_ci 2035bf215546Sopenharmony_ci if (trans->base.b.usage & PIPE_MAP_WRITE) { 2036bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pctx->screen); 2037bf215546Sopenharmony_ci struct zink_resource *m = trans->staging_res ? zink_resource(trans->staging_res) : 2038bf215546Sopenharmony_ci res; 2039bf215546Sopenharmony_ci ASSERTED VkDeviceSize size, src_offset, dst_offset = 0; 2040bf215546Sopenharmony_ci if (m->obj->is_buffer) { 2041bf215546Sopenharmony_ci size = box->width; 2042bf215546Sopenharmony_ci src_offset = box->x + (trans->staging_res ? trans->offset : ptrans->box.x); 2043bf215546Sopenharmony_ci dst_offset = box->x + ptrans->box.x; 2044bf215546Sopenharmony_ci } else { 2045bf215546Sopenharmony_ci size = (VkDeviceSize)box->width * box->height * util_format_get_blocksize(m->base.b.format); 2046bf215546Sopenharmony_ci src_offset = trans->offset + 2047bf215546Sopenharmony_ci box->z * trans->depthPitch + 2048bf215546Sopenharmony_ci util_format_get_2d_size(m->base.b.format, trans->base.b.stride, box->y) + 2049bf215546Sopenharmony_ci util_format_get_stride(m->base.b.format, box->x); 2050bf215546Sopenharmony_ci assert(src_offset + size <= res->obj->size); 2051bf215546Sopenharmony_ci } 2052bf215546Sopenharmony_ci if (!m->obj->coherent) { 2053bf215546Sopenharmony_ci VkMappedMemoryRange range = zink_resource_init_mem_range(screen, m->obj, m->obj->offset, m->obj->size); 2054bf215546Sopenharmony_ci if (VKSCR(FlushMappedMemoryRanges)(screen->dev, 1, &range) != VK_SUCCESS) { 2055bf215546Sopenharmony_ci mesa_loge("ZINK: vkFlushMappedMemoryRanges failed"); 2056bf215546Sopenharmony_ci } 2057bf215546Sopenharmony_ci } 2058bf215546Sopenharmony_ci if (trans->staging_res) { 2059bf215546Sopenharmony_ci struct zink_resource *staging_res = zink_resource(trans->staging_res); 2060bf215546Sopenharmony_ci 2061bf215546Sopenharmony_ci if (ptrans->resource->target == PIPE_BUFFER) 2062bf215546Sopenharmony_ci zink_copy_buffer(ctx, res, staging_res, dst_offset, src_offset, size); 2063bf215546Sopenharmony_ci else 2064bf215546Sopenharmony_ci zink_transfer_copy_bufimage(ctx, res, staging_res, trans); 2065bf215546Sopenharmony_ci } 2066bf215546Sopenharmony_ci } 2067bf215546Sopenharmony_ci} 2068bf215546Sopenharmony_ci 2069bf215546Sopenharmony_cistatic void 2070bf215546Sopenharmony_citransfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) 2071bf215546Sopenharmony_ci{ 2072bf215546Sopenharmony_ci struct zink_context *ctx = zink_context(pctx); 2073bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(ptrans->resource); 2074bf215546Sopenharmony_ci struct zink_transfer *trans = (struct zink_transfer *)ptrans; 2075bf215546Sopenharmony_ci 2076bf215546Sopenharmony_ci if (!(trans->base.b.usage & (PIPE_MAP_FLUSH_EXPLICIT | PIPE_MAP_COHERENT))) { 2077bf215546Sopenharmony_ci /* flush_region is relative to the mapped region: use only the extents */ 2078bf215546Sopenharmony_ci struct pipe_box box = ptrans->box; 2079bf215546Sopenharmony_ci box.x = box.y = box.z = 0; 2080bf215546Sopenharmony_ci zink_transfer_flush_region(pctx, ptrans, &box); 2081bf215546Sopenharmony_ci } 2082bf215546Sopenharmony_ci 2083bf215546Sopenharmony_ci if ((trans->base.b.usage & PIPE_MAP_PERSISTENT) && !(trans->base.b.usage & PIPE_MAP_COHERENT)) 2084bf215546Sopenharmony_ci res->obj->persistent_maps--; 2085bf215546Sopenharmony_ci 2086bf215546Sopenharmony_ci if (trans->staging_res) 2087bf215546Sopenharmony_ci pipe_resource_reference(&trans->staging_res, NULL); 2088bf215546Sopenharmony_ci pipe_resource_reference(&trans->base.b.resource, NULL); 2089bf215546Sopenharmony_ci 2090bf215546Sopenharmony_ci destroy_transfer(ctx, trans); 2091bf215546Sopenharmony_ci} 2092bf215546Sopenharmony_ci 2093bf215546Sopenharmony_cistatic void 2094bf215546Sopenharmony_cido_transfer_unmap(struct zink_screen *screen, struct zink_transfer *trans) 2095bf215546Sopenharmony_ci{ 2096bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(trans->staging_res); 2097bf215546Sopenharmony_ci if (!res) 2098bf215546Sopenharmony_ci res = zink_resource(trans->base.b.resource); 2099bf215546Sopenharmony_ci unmap_resource(screen, res); 2100bf215546Sopenharmony_ci} 2101bf215546Sopenharmony_ci 2102bf215546Sopenharmony_cistatic void 2103bf215546Sopenharmony_cizink_buffer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) 2104bf215546Sopenharmony_ci{ 2105bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pctx->screen); 2106bf215546Sopenharmony_ci struct zink_transfer *trans = (struct zink_transfer *)ptrans; 2107bf215546Sopenharmony_ci if (trans->base.b.usage & PIPE_MAP_ONCE && !trans->staging_res) 2108bf215546Sopenharmony_ci do_transfer_unmap(screen, trans); 2109bf215546Sopenharmony_ci transfer_unmap(pctx, ptrans); 2110bf215546Sopenharmony_ci} 2111bf215546Sopenharmony_ci 2112bf215546Sopenharmony_cistatic void 2113bf215546Sopenharmony_cizink_image_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) 2114bf215546Sopenharmony_ci{ 2115bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pctx->screen); 2116bf215546Sopenharmony_ci struct zink_transfer *trans = (struct zink_transfer *)ptrans; 2117bf215546Sopenharmony_ci if (sizeof(void*) == 4) 2118bf215546Sopenharmony_ci do_transfer_unmap(screen, trans); 2119bf215546Sopenharmony_ci transfer_unmap(pctx, ptrans); 2120bf215546Sopenharmony_ci} 2121bf215546Sopenharmony_ci 2122bf215546Sopenharmony_cistatic void 2123bf215546Sopenharmony_cizink_buffer_subdata(struct pipe_context *ctx, struct pipe_resource *buffer, 2124bf215546Sopenharmony_ci unsigned usage, unsigned offset, unsigned size, const void *data) 2125bf215546Sopenharmony_ci{ 2126bf215546Sopenharmony_ci struct pipe_transfer *transfer = NULL; 2127bf215546Sopenharmony_ci struct pipe_box box; 2128bf215546Sopenharmony_ci uint8_t *map = NULL; 2129bf215546Sopenharmony_ci 2130bf215546Sopenharmony_ci usage |= PIPE_MAP_WRITE; 2131bf215546Sopenharmony_ci 2132bf215546Sopenharmony_ci if (!(usage & PIPE_MAP_DIRECTLY)) 2133bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_RANGE; 2134bf215546Sopenharmony_ci 2135bf215546Sopenharmony_ci u_box_1d(offset, size, &box); 2136bf215546Sopenharmony_ci map = zink_buffer_map(ctx, buffer, 0, usage, &box, &transfer); 2137bf215546Sopenharmony_ci if (!map) 2138bf215546Sopenharmony_ci return; 2139bf215546Sopenharmony_ci 2140bf215546Sopenharmony_ci memcpy(map, data, size); 2141bf215546Sopenharmony_ci zink_buffer_unmap(ctx, transfer); 2142bf215546Sopenharmony_ci} 2143bf215546Sopenharmony_ci 2144bf215546Sopenharmony_cistatic struct pipe_resource * 2145bf215546Sopenharmony_cizink_resource_get_separate_stencil(struct pipe_resource *pres) 2146bf215546Sopenharmony_ci{ 2147bf215546Sopenharmony_ci /* For packed depth-stencil, we treat depth as the primary resource 2148bf215546Sopenharmony_ci * and store S8 as the "second plane" resource. 2149bf215546Sopenharmony_ci */ 2150bf215546Sopenharmony_ci if (pres->next && pres->next->format == PIPE_FORMAT_S8_UINT) 2151bf215546Sopenharmony_ci return pres->next; 2152bf215546Sopenharmony_ci 2153bf215546Sopenharmony_ci return NULL; 2154bf215546Sopenharmony_ci 2155bf215546Sopenharmony_ci} 2156bf215546Sopenharmony_ci 2157bf215546Sopenharmony_cibool 2158bf215546Sopenharmony_cizink_resource_object_init_storage(struct zink_context *ctx, struct zink_resource *res) 2159bf215546Sopenharmony_ci{ 2160bf215546Sopenharmony_ci /* base resource already has the cap */ 2161bf215546Sopenharmony_ci if (res->base.b.bind & PIPE_BIND_SHADER_IMAGE) 2162bf215546Sopenharmony_ci return true; 2163bf215546Sopenharmony_ci if (res->obj->is_buffer) { 2164bf215546Sopenharmony_ci unreachable("zink: all buffers should have this bit"); 2165bf215546Sopenharmony_ci return true; 2166bf215546Sopenharmony_ci } 2167bf215546Sopenharmony_ci assert(!res->obj->dt); 2168bf215546Sopenharmony_ci zink_fb_clears_apply_region(ctx, &res->base.b, (struct u_rect){0, res->base.b.width0, 0, res->base.b.height0}); 2169bf215546Sopenharmony_ci bool ret = add_resource_bind(ctx, res, PIPE_BIND_SHADER_IMAGE); 2170bf215546Sopenharmony_ci if (ret) 2171bf215546Sopenharmony_ci zink_resource_rebind(ctx, res); 2172bf215546Sopenharmony_ci 2173bf215546Sopenharmony_ci return ret; 2174bf215546Sopenharmony_ci} 2175bf215546Sopenharmony_ci 2176bf215546Sopenharmony_civoid 2177bf215546Sopenharmony_cizink_resource_setup_transfer_layouts(struct zink_context *ctx, struct zink_resource *src, struct zink_resource *dst) 2178bf215546Sopenharmony_ci{ 2179bf215546Sopenharmony_ci if (src == dst) { 2180bf215546Sopenharmony_ci /* The Vulkan 1.1 specification says the following about valid usage 2181bf215546Sopenharmony_ci * of vkCmdBlitImage: 2182bf215546Sopenharmony_ci * 2183bf215546Sopenharmony_ci * "srcImageLayout must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, 2184bf215546Sopenharmony_ci * VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL" 2185bf215546Sopenharmony_ci * 2186bf215546Sopenharmony_ci * and: 2187bf215546Sopenharmony_ci * 2188bf215546Sopenharmony_ci * "dstImageLayout must be VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, 2189bf215546Sopenharmony_ci * VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL" 2190bf215546Sopenharmony_ci * 2191bf215546Sopenharmony_ci * Since we cant have the same image in two states at the same time, 2192bf215546Sopenharmony_ci * we're effectively left with VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or 2193bf215546Sopenharmony_ci * VK_IMAGE_LAYOUT_GENERAL. And since this isn't a present-related 2194bf215546Sopenharmony_ci * operation, VK_IMAGE_LAYOUT_GENERAL seems most appropriate. 2195bf215546Sopenharmony_ci */ 2196bf215546Sopenharmony_ci zink_resource_image_barrier(ctx, src, 2197bf215546Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL, 2198bf215546Sopenharmony_ci VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, 2199bf215546Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT); 2200bf215546Sopenharmony_ci } else { 2201bf215546Sopenharmony_ci zink_resource_image_barrier(ctx, src, 2202bf215546Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 2203bf215546Sopenharmony_ci VK_ACCESS_TRANSFER_READ_BIT, 2204bf215546Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT); 2205bf215546Sopenharmony_ci 2206bf215546Sopenharmony_ci zink_resource_image_barrier(ctx, dst, 2207bf215546Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 2208bf215546Sopenharmony_ci VK_ACCESS_TRANSFER_WRITE_BIT, 2209bf215546Sopenharmony_ci VK_PIPELINE_STAGE_TRANSFER_BIT); 2210bf215546Sopenharmony_ci } 2211bf215546Sopenharmony_ci} 2212bf215546Sopenharmony_ci 2213bf215546Sopenharmony_civoid 2214bf215546Sopenharmony_cizink_get_depth_stencil_resources(struct pipe_resource *res, 2215bf215546Sopenharmony_ci struct zink_resource **out_z, 2216bf215546Sopenharmony_ci struct zink_resource **out_s) 2217bf215546Sopenharmony_ci{ 2218bf215546Sopenharmony_ci if (!res) { 2219bf215546Sopenharmony_ci if (out_z) *out_z = NULL; 2220bf215546Sopenharmony_ci if (out_s) *out_s = NULL; 2221bf215546Sopenharmony_ci return; 2222bf215546Sopenharmony_ci } 2223bf215546Sopenharmony_ci 2224bf215546Sopenharmony_ci if (res->format != PIPE_FORMAT_S8_UINT) { 2225bf215546Sopenharmony_ci if (out_z) *out_z = zink_resource(res); 2226bf215546Sopenharmony_ci if (out_s) *out_s = zink_resource(zink_resource_get_separate_stencil(res)); 2227bf215546Sopenharmony_ci } else { 2228bf215546Sopenharmony_ci if (out_z) *out_z = NULL; 2229bf215546Sopenharmony_ci if (out_s) *out_s = zink_resource(res); 2230bf215546Sopenharmony_ci } 2231bf215546Sopenharmony_ci} 2232bf215546Sopenharmony_ci 2233bf215546Sopenharmony_cistatic void 2234bf215546Sopenharmony_cizink_resource_set_separate_stencil(struct pipe_resource *pres, 2235bf215546Sopenharmony_ci struct pipe_resource *stencil) 2236bf215546Sopenharmony_ci{ 2237bf215546Sopenharmony_ci assert(util_format_has_depth(util_format_description(pres->format))); 2238bf215546Sopenharmony_ci pipe_resource_reference(&pres->next, stencil); 2239bf215546Sopenharmony_ci} 2240bf215546Sopenharmony_ci 2241bf215546Sopenharmony_cistatic enum pipe_format 2242bf215546Sopenharmony_cizink_resource_get_internal_format(struct pipe_resource *pres) 2243bf215546Sopenharmony_ci{ 2244bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(pres); 2245bf215546Sopenharmony_ci return res->internal_format; 2246bf215546Sopenharmony_ci} 2247bf215546Sopenharmony_ci 2248bf215546Sopenharmony_cistatic const struct u_transfer_vtbl transfer_vtbl = { 2249bf215546Sopenharmony_ci .resource_create = zink_resource_create, 2250bf215546Sopenharmony_ci .resource_destroy = zink_resource_destroy, 2251bf215546Sopenharmony_ci .transfer_map = zink_image_map, 2252bf215546Sopenharmony_ci .transfer_unmap = zink_image_unmap, 2253bf215546Sopenharmony_ci .transfer_flush_region = zink_transfer_flush_region, 2254bf215546Sopenharmony_ci .get_internal_format = zink_resource_get_internal_format, 2255bf215546Sopenharmony_ci .set_stencil = zink_resource_set_separate_stencil, 2256bf215546Sopenharmony_ci .get_stencil = zink_resource_get_separate_stencil, 2257bf215546Sopenharmony_ci}; 2258bf215546Sopenharmony_ci 2259bf215546Sopenharmony_cibool 2260bf215546Sopenharmony_cizink_screen_resource_init(struct pipe_screen *pscreen) 2261bf215546Sopenharmony_ci{ 2262bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(pscreen); 2263bf215546Sopenharmony_ci pscreen->resource_create = zink_resource_create; 2264bf215546Sopenharmony_ci pscreen->resource_create_with_modifiers = zink_resource_create_with_modifiers; 2265bf215546Sopenharmony_ci pscreen->resource_create_drawable = zink_resource_create_drawable; 2266bf215546Sopenharmony_ci pscreen->resource_destroy = zink_resource_destroy; 2267bf215546Sopenharmony_ci pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, true, true, false, false, !screen->have_D24_UNORM_S8_UINT); 2268bf215546Sopenharmony_ci 2269bf215546Sopenharmony_ci if (screen->info.have_KHR_external_memory_fd || screen->info.have_KHR_external_memory_win32) { 2270bf215546Sopenharmony_ci pscreen->resource_get_handle = zink_resource_get_handle; 2271bf215546Sopenharmony_ci pscreen->resource_from_handle = zink_resource_from_handle; 2272bf215546Sopenharmony_ci } 2273bf215546Sopenharmony_ci if (screen->instance_info.have_KHR_external_memory_capabilities) { 2274bf215546Sopenharmony_ci pscreen->memobj_create_from_handle = zink_memobj_create_from_handle; 2275bf215546Sopenharmony_ci pscreen->memobj_destroy = zink_memobj_destroy; 2276bf215546Sopenharmony_ci pscreen->resource_from_memobj = zink_resource_from_memobj; 2277bf215546Sopenharmony_ci } 2278bf215546Sopenharmony_ci pscreen->resource_get_param = zink_resource_get_param; 2279bf215546Sopenharmony_ci return true; 2280bf215546Sopenharmony_ci} 2281bf215546Sopenharmony_ci 2282bf215546Sopenharmony_civoid 2283bf215546Sopenharmony_cizink_context_resource_init(struct pipe_context *pctx) 2284bf215546Sopenharmony_ci{ 2285bf215546Sopenharmony_ci pctx->buffer_map = zink_buffer_map; 2286bf215546Sopenharmony_ci pctx->buffer_unmap = zink_buffer_unmap; 2287bf215546Sopenharmony_ci pctx->texture_map = u_transfer_helper_deinterleave_transfer_map; 2288bf215546Sopenharmony_ci pctx->texture_unmap = u_transfer_helper_deinterleave_transfer_unmap; 2289bf215546Sopenharmony_ci 2290bf215546Sopenharmony_ci pctx->transfer_flush_region = u_transfer_helper_transfer_flush_region; 2291bf215546Sopenharmony_ci pctx->buffer_subdata = zink_buffer_subdata; 2292bf215546Sopenharmony_ci pctx->texture_subdata = u_default_texture_subdata; 2293bf215546Sopenharmony_ci pctx->invalidate_resource = zink_resource_invalidate; 2294bf215546Sopenharmony_ci} 2295