radv_android.c revision b8e80941
1/* 2 * Copyright © 2017, Google Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <hardware/gralloc.h> 25#include <hardware/hardware.h> 26#include <hardware/hwvulkan.h> 27#include <vulkan/vk_android_native_buffer.h> 28#include <vulkan/vk_icd.h> 29#include <libsync.h> 30 31#include "radv_private.h" 32 33static int radv_hal_open(const struct hw_module_t* mod, const char* id, struct hw_device_t** dev); 34static int radv_hal_close(struct hw_device_t *dev); 35 36static void UNUSED 37static_asserts(void) 38{ 39 STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC); 40} 41 42PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = { 43 .common = { 44 .tag = HARDWARE_MODULE_TAG, 45 .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1, 46 .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0), 47 .id = HWVULKAN_HARDWARE_MODULE_ID, 48 .name = "AMD Vulkan HAL", 49 .author = "Google", 50 .methods = &(hw_module_methods_t) { 51 .open = radv_hal_open, 52 }, 53 }, 54}; 55 56/* If any bits in test_mask are set, then unset them and return true. */ 57static inline bool 58unmask32(uint32_t *inout_mask, uint32_t test_mask) 59{ 60 uint32_t orig_mask = *inout_mask; 61 *inout_mask &= ~test_mask; 62 return *inout_mask != orig_mask; 63} 64 65static int 66radv_hal_open(const struct hw_module_t* mod, const char* id, 67 struct hw_device_t** dev) 68{ 69 assert(mod == &HAL_MODULE_INFO_SYM.common); 70 assert(strcmp(id, HWVULKAN_DEVICE_0) == 0); 71 72 hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev)); 73 if (!hal_dev) 74 return -1; 75 76 *hal_dev = (hwvulkan_device_t) { 77 .common = { 78 .tag = HARDWARE_DEVICE_TAG, 79 .version = HWVULKAN_DEVICE_API_VERSION_0_1, 80 .module = &HAL_MODULE_INFO_SYM.common, 81 .close = radv_hal_close, 82 }, 83 .EnumerateInstanceExtensionProperties = radv_EnumerateInstanceExtensionProperties, 84 .CreateInstance = radv_CreateInstance, 85 .GetInstanceProcAddr = radv_GetInstanceProcAddr, 86 }; 87 88 *dev = &hal_dev->common; 89 return 0; 90} 91 92static int 93radv_hal_close(struct hw_device_t *dev) 94{ 95 /* hwvulkan.h claims that hw_device_t::close() is never called. */ 96 return -1; 97} 98 99VkResult 100radv_image_from_gralloc(VkDevice device_h, 101 const VkImageCreateInfo *base_info, 102 const VkNativeBufferANDROID *gralloc_info, 103 const VkAllocationCallbacks *alloc, 104 VkImage *out_image_h) 105 106{ 107 RADV_FROM_HANDLE(radv_device, device, device_h); 108 VkImage image_h = VK_NULL_HANDLE; 109 struct radv_image *image = NULL; 110 struct radv_bo *bo = NULL; 111 VkResult result; 112 113 if (gralloc_info->handle->numFds != 1) { 114 return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE, 115 "VkNativeBufferANDROID::handle::numFds is %d, " 116 "expected 1", gralloc_info->handle->numFds); 117 } 118 119 /* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf 120 * must exceed that of the gralloc handle, and we do not own the gralloc 121 * handle. 122 */ 123 int dma_buf = gralloc_info->handle->data[0]; 124 125 VkDeviceMemory memory_h; 126 127 const VkImportMemoryFdInfoKHR import_info = { 128 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, 129 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, 130 .fd = dup(dma_buf), 131 }; 132 133 /* Find the first VRAM memory type, or GART for PRIME images. */ 134 int memory_type_index = -1; 135 for (int i = 0; i < device->physical_device->memory_properties.memoryTypeCount; ++i) { 136 bool is_local = !!(device->physical_device->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 137 if (is_local) { 138 memory_type_index = i; 139 break; 140 } 141 } 142 143 /* fallback */ 144 if (memory_type_index == -1) 145 memory_type_index = 0; 146 147 result = radv_AllocateMemory(device_h, 148 &(VkMemoryAllocateInfo) { 149 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 150 .pNext = &import_info, 151 /* Max buffer size, unused for imports */ 152 .allocationSize = 0x7FFFFFFF, 153 .memoryTypeIndex = memory_type_index, 154 }, 155 alloc, 156 &memory_h); 157 if (result != VK_SUCCESS) 158 return result; 159 160 struct radeon_bo_metadata md; 161 device->ws->buffer_get_metadata(radv_device_memory_from_handle(memory_h)->bo, &md); 162 163 bool is_scanout; 164 if (device->physical_device->rad_info.chip_class >= GFX9) { 165 /* Copied from radeonsi, but is hacky so should be cleaned up. */ 166 is_scanout = md.u.gfx9.swizzle_mode == 0 || md.u.gfx9.swizzle_mode % 4 == 2; 167 } else { 168 is_scanout = md.u.legacy.scanout; 169 } 170 171 VkImageCreateInfo updated_base_info = *base_info; 172 173 VkExternalMemoryImageCreateInfo external_memory_info = { 174 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, 175 .pNext = updated_base_info.pNext, 176 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 177 }; 178 179 updated_base_info.pNext = &external_memory_info; 180 181 result = radv_image_create(device_h, 182 &(struct radv_image_create_info) { 183 .vk_info = &updated_base_info, 184 .scanout = is_scanout, 185 .no_metadata_planes = true}, 186 alloc, 187 &image_h); 188 189 if (result != VK_SUCCESS) 190 goto fail_create_image; 191 192 image = radv_image_from_handle(image_h); 193 194 radv_BindImageMemory(device_h, image_h, memory_h, 0); 195 196 image->owned_memory = memory_h; 197 /* Don't clobber the out-parameter until success is certain. */ 198 *out_image_h = image_h; 199 200 return VK_SUCCESS; 201 202fail_create_image: 203 radv_FreeMemory(device_h, memory_h, alloc); 204 return result; 205} 206 207VkResult radv_GetSwapchainGrallocUsageANDROID( 208 VkDevice device_h, 209 VkFormat format, 210 VkImageUsageFlags imageUsage, 211 int* grallocUsage) 212{ 213 RADV_FROM_HANDLE(radv_device, device, device_h); 214 struct radv_physical_device *phys_dev = device->physical_device; 215 VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev); 216 VkResult result; 217 218 *grallocUsage = 0; 219 220 /* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags 221 * returned to applications via VkSurfaceCapabilitiesKHR::supportedUsageFlags. 222 * The relevant code in libvulkan/swapchain.cpp contains this fun comment: 223 * 224 * TODO(jessehall): I think these are right, but haven't thought hard 225 * about it. Do we need to query the driver for support of any of 226 * these? 227 * 228 * Any disagreement between this function and the hardcoded 229 * VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests 230 * dEQP-VK.wsi.android.swapchain.*.image_usage to fail. 231 */ 232 233 const VkPhysicalDeviceImageFormatInfo2 image_format_info = { 234 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, 235 .format = format, 236 .type = VK_IMAGE_TYPE_2D, 237 .tiling = VK_IMAGE_TILING_OPTIMAL, 238 .usage = imageUsage, 239 }; 240 241 VkImageFormatProperties2 image_format_props = { 242 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, 243 }; 244 245 /* Check that requested format and usage are supported. */ 246 result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h, 247 &image_format_info, &image_format_props); 248 if (result != VK_SUCCESS) { 249 return vk_errorf(device->instance, result, 250 "radv_GetPhysicalDeviceImageFormatProperties2 failed " 251 "inside %s", __func__); 252 } 253 254 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT | 255 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) 256 *grallocUsage |= GRALLOC_USAGE_HW_RENDER; 257 258 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 259 VK_IMAGE_USAGE_SAMPLED_BIT | 260 VK_IMAGE_USAGE_STORAGE_BIT | 261 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) 262 *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE; 263 264 /* All VkImageUsageFlags not explicitly checked here are unsupported for 265 * gralloc swapchains. 266 */ 267 if (imageUsage != 0) { 268 return vk_errorf(device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED, 269 "unsupported VkImageUsageFlags(0x%x) for gralloc " 270 "swapchain", imageUsage); 271 } 272 273 /* 274 * FINISHME: Advertise all display-supported formats. Mostly 275 * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check 276 * what we need for 30-bit colors. 277 */ 278 if (format == VK_FORMAT_B8G8R8A8_UNORM || 279 format == VK_FORMAT_B5G6R5_UNORM_PACK16) { 280 *grallocUsage |= GRALLOC_USAGE_HW_FB | 281 GRALLOC_USAGE_HW_COMPOSER | 282 GRALLOC_USAGE_EXTERNAL_DISP; 283 } 284 285 if (*grallocUsage == 0) 286 return VK_ERROR_FORMAT_NOT_SUPPORTED; 287 288 return VK_SUCCESS; 289} 290 291VkResult 292radv_AcquireImageANDROID( 293 VkDevice device, 294 VkImage image_h, 295 int nativeFenceFd, 296 VkSemaphore semaphore, 297 VkFence fence) 298{ 299 VkResult semaphore_result = VK_SUCCESS, fence_result = VK_SUCCESS; 300 301 if (semaphore != VK_NULL_HANDLE) { 302 int semaphore_fd = nativeFenceFd >= 0 ? dup(nativeFenceFd) : nativeFenceFd; 303 semaphore_result = radv_ImportSemaphoreFdKHR(device, 304 &(VkImportSemaphoreFdInfoKHR) { 305 .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, 306 .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, 307 .fd = semaphore_fd, 308 .semaphore = semaphore, 309 }); 310 } 311 312 if (fence != VK_NULL_HANDLE) { 313 int fence_fd = nativeFenceFd >= 0 ? dup(nativeFenceFd) : nativeFenceFd; 314 fence_result = radv_ImportFenceFdKHR(device, 315 &(VkImportFenceFdInfoKHR) { 316 .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, 317 .flags = VK_FENCE_IMPORT_TEMPORARY_BIT, 318 .fd = fence_fd, 319 .fence = fence, 320 }); 321 } 322 323 close(nativeFenceFd); 324 325 if (semaphore_result != VK_SUCCESS) 326 return semaphore_result; 327 return fence_result; 328} 329 330VkResult 331radv_QueueSignalReleaseImageANDROID( 332 VkQueue _queue, 333 uint32_t waitSemaphoreCount, 334 const VkSemaphore* pWaitSemaphores, 335 VkImage image, 336 int* pNativeFenceFd) 337{ 338 RADV_FROM_HANDLE(radv_queue, queue, _queue); 339 VkResult result = VK_SUCCESS; 340 341 if (waitSemaphoreCount == 0) { 342 if (pNativeFenceFd) 343 *pNativeFenceFd = -1; 344 return VK_SUCCESS; 345 } 346 347 int fd = -1; 348 349 for (uint32_t i = 0; i < waitSemaphoreCount; ++i) { 350 int tmp_fd; 351 result = radv_GetSemaphoreFdKHR(radv_device_to_handle(queue->device), 352 &(VkSemaphoreGetFdInfoKHR) { 353 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, 354 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, 355 .semaphore = pWaitSemaphores[i], 356 }, &tmp_fd); 357 if (result != VK_SUCCESS) { 358 if (fd >= 0) 359 close (fd); 360 return result; 361 } 362 363 if (fd < 0) 364 fd = tmp_fd; 365 else if (tmp_fd >= 0) { 366 sync_accumulate("radv", &fd, tmp_fd); 367 close(tmp_fd); 368 } 369 } 370 371 if (pNativeFenceFd) { 372 *pNativeFenceFd = fd; 373 } else if (fd >= 0) { 374 close(fd); 375 /* We still need to do the exports, to reset the semaphores, but 376 * otherwise we don't wait on them. */ 377 } 378 return VK_SUCCESS; 379} 380