radv: move RADV_TRACE_FILE functions to radv_debug.c
[mesa.git] / src / amd / vulkan / radv_device.c
index 59c4ea8448ee6c3662a1c9ddcb386323d3c3bb69..aae3488318390d51b1719fccaf943d3af474a712 100644 (file)
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include "radv_debug.h"
 #include "radv_private.h"
 #include "radv_cs.h"
 #include "util/disk_cache.h"
@@ -63,12 +64,15 @@ radv_device_get_cache_uuid(enum radeon_family family, void *uuid)
 }
 
 static void
-radv_get_device_uuid(drmDevicePtr device, void *uuid) {
-       memset(uuid, 0, VK_UUID_SIZE);
-       memcpy((char*)uuid + 0, &device->businfo.pci->domain, 2);
-       memcpy((char*)uuid + 2, &device->businfo.pci->bus, 1);
-       memcpy((char*)uuid + 3, &device->businfo.pci->dev, 1);
-       memcpy((char*)uuid + 4, &device->businfo.pci->func, 1);
+radv_get_driver_uuid(void *uuid)
+{
+       ac_compute_driver_uuid(uuid, VK_UUID_SIZE);
+}
+
+static void
+radv_get_device_uuid(struct radeon_info *info, void *uuid)
+{
+       ac_compute_device_uuid(info, uuid, VK_UUID_SIZE);
 }
 
 static const VkExtensionProperties instance_extensions[] = {
@@ -91,13 +95,21 @@ static const VkExtensionProperties instance_extensions[] = {
 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
        {
                .extensionName = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
-               .specVersion = 5,
+               .specVersion = 6,
        },
 #endif
        {
                .extensionName = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
                .specVersion = 1,
        },
+       {
+               .extensionName = VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+               .specVersion = 1,
+       },
+       {
+               .extensionName = VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
+               .specVersion = 1,
+       },
 };
 
 static const VkExtensionProperties common_device_extensions[] = {
@@ -134,15 +146,41 @@ static const VkExtensionProperties common_device_extensions[] = {
                .specVersion = 1,
        },
        {
-               .extensionName = VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME,
+               .extensionName = VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
                .specVersion = 1,
        },
        {
-               .extensionName = VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
+               .extensionName = VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
                .specVersion = 1,
        },
        {
-               .extensionName = VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
+               .extensionName = VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
+               .specVersion = 1,
+       },
+       {
+               .extensionName = VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
+               .specVersion = 1,
+       },
+       {
+               .extensionName = VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME,
+               .specVersion = 1,
+       },
+       {
+               .extensionName = VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME,
+               .specVersion = 1,
+       },
+};
+static const VkExtensionProperties ext_sema_device_extensions[] = {
+       {
+               .extensionName = VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
+               .specVersion = 1,
+       },
+       {
+               .extensionName = VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
+               .specVersion = 1,
+       },
+       {
+               .extensionName = VK_KHX_MULTIVIEW_EXTENSION_NAME,
                .specVersion = 1,
        },
 };
@@ -281,7 +319,7 @@ radv_physical_device_init(struct radv_physical_device *device,
                goto fail;
        }
 
-       if (radv_device_get_cache_uuid(device->rad_info.family, device->uuid)) {
+       if (radv_device_get_cache_uuid(device->rad_info.family, device->cache_uuid)) {
                radv_finish_wsi(device);
                device->ws->destroy(device->ws);
                result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
@@ -296,10 +334,20 @@ radv_physical_device_init(struct radv_physical_device *device,
        if (result != VK_SUCCESS)
                goto fail;
 
+       if (device->rad_info.has_syncobj) {
+               result = radv_extensions_register(instance,
+                                                 &device->extensions,
+                                                 ext_sema_device_extensions,
+                                                 ARRAY_SIZE(ext_sema_device_extensions));
+               if (result != VK_SUCCESS)
+                       goto fail;
+       }
+
        fprintf(stderr, "WARNING: radv is not a conformant vulkan implementation, testing use only.\n");
        device->name = get_chip_name(device->rad_info.family);
 
-       radv_get_device_uuid(drm_device, device->device_uuid);
+       radv_get_driver_uuid(&device->device_uuid);
+       radv_get_device_uuid(&device->rad_info, &device->device_uuid);
 
        if (device->rad_info.family == CHIP_STONEY ||
            device->rad_info.chip_class >= GFX9) {
@@ -531,7 +579,7 @@ void radv_GetPhysicalDeviceFeatures(
                .independentBlend                         = true,
                .geometryShader                           = !is_gfx9,
                .tessellationShader                       = !is_gfx9,
-               .sampleRateShading                        = false,
+               .sampleRateShading                        = true,
                .dualSrcBlend                             = true,
                .logicOp                                  = true,
                .multiDrawIndirect                        = true,
@@ -577,6 +625,25 @@ void radv_GetPhysicalDeviceFeatures2KHR(
        VkPhysicalDevice                            physicalDevice,
        VkPhysicalDeviceFeatures2KHR               *pFeatures)
 {
+       vk_foreach_struct(ext, pFeatures->pNext) {
+               switch (ext->sType) {
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR: {
+                       VkPhysicalDeviceVariablePointerFeaturesKHR *features = (void *)ext;
+                       features->variablePointersStorageBuffer = true;
+                       features->variablePointers = false;
+                       break;
+               }
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX: {
+                       VkPhysicalDeviceMultiviewFeaturesKHX *features = (VkPhysicalDeviceMultiviewFeaturesKHX*)ext;
+                       features->multiview = true;
+                       features->multiviewGeometryShader = true;
+                       features->multiviewTessellationShader = true;
+                       break;
+               }
+               default:
+                       break;
+               }
+       }
        return radv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
 }
 
@@ -724,13 +791,14 @@ void radv_GetPhysicalDeviceProperties(
        };
 
        strcpy(pProperties->deviceName, pdevice->name);
-       memcpy(pProperties->pipelineCacheUUID, pdevice->uuid, VK_UUID_SIZE);
+       memcpy(pProperties->pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
 }
 
 void radv_GetPhysicalDeviceProperties2KHR(
        VkPhysicalDevice                            physicalDevice,
        VkPhysicalDeviceProperties2KHR             *pProperties)
 {
+       RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice);
        radv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
 
        vk_foreach_struct(ext, pProperties->pNext) {
@@ -741,6 +809,19 @@ void radv_GetPhysicalDeviceProperties2KHR(
                        properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
                        break;
                }
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR: {
+                       VkPhysicalDeviceIDPropertiesKHR *properties = (VkPhysicalDeviceIDPropertiesKHR*)ext;
+                       memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
+                       memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
+                       properties->deviceLUIDValid = false;
+                       break;
+               }
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX: {
+                       VkPhysicalDeviceMultiviewPropertiesKHX *properties = (VkPhysicalDeviceMultiviewPropertiesKHX*)ext;
+                       properties->maxMultiviewViewCount = MAX_VIEWS;
+                       properties->maxMultiviewInstanceIndex = INT_MAX;
+                       break;
+               }
                default:
                        break;
                }
@@ -869,15 +950,17 @@ void radv_GetPhysicalDeviceMemoryProperties(
        };
 
        STATIC_ASSERT(RADV_MEM_HEAP_COUNT <= VK_MAX_MEMORY_HEAPS);
+       uint64_t visible_vram_size = MIN2(physical_device->rad_info.vram_size,
+                                         physical_device->rad_info.vram_vis_size);
 
        pMemoryProperties->memoryHeapCount = RADV_MEM_HEAP_COUNT;
        pMemoryProperties->memoryHeaps[RADV_MEM_HEAP_VRAM] = (VkMemoryHeap) {
                .size = physical_device->rad_info.vram_size -
-                               physical_device->rad_info.vram_vis_size,
+                               visible_vram_size,
                .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
        };
        pMemoryProperties->memoryHeaps[RADV_MEM_HEAP_VRAM_CPU_ACCESS] = (VkMemoryHeap) {
-               .size = physical_device->rad_info.vram_vis_size,
+               .size = visible_vram_size,
                .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
        };
        pMemoryProperties->memoryHeaps[RADV_MEM_HEAP_GTT] = (VkMemoryHeap) {
@@ -986,6 +1069,19 @@ VkResult radv_CreateDevice(
                        return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
        }
 
+       /* Check enabled features */
+       if (pCreateInfo->pEnabledFeatures) {
+               VkPhysicalDeviceFeatures supported_features;
+               radv_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
+               VkBool32 *supported_feature = (VkBool32 *)&supported_features;
+               VkBool32 *enabled_feature = (VkBool32 *)pCreateInfo->pEnabledFeatures;
+               unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
+               for (uint32_t i = 0; i < num_features; i++) {
+                       if (enabled_feature[i] && !supported_feature[i])
+                               return vk_error(VK_ERROR_FEATURE_NOT_PRESENT);
+               }
+       }
+
        device = vk_alloc2(&physical_device->instance->alloc, pAllocator,
                             sizeof(*device), 8,
                             VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
@@ -1006,6 +1102,9 @@ VkResult radv_CreateDevice(
        else
                device->alloc = physical_device->instance->alloc;
 
+       mtx_init(&device->shader_slab_mutex, mtx_plain);
+       list_inithead(&device->shader_slabs);
+
        for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
                const VkDeviceQueueCreateInfo *queue_create = &pCreateInfo->pQueueCreateInfos[i];
                uint32_t qfi = queue_create->queueFamilyIndex;
@@ -1116,13 +1215,7 @@ VkResult radv_CreateDevice(
        }
 
        if (getenv("RADV_TRACE_FILE")) {
-               device->trace_bo = device->ws->buffer_create(device->ws, 4096, 8,
-                                                            RADEON_DOMAIN_VRAM, RADEON_FLAG_CPU_ACCESS);
-               if (!device->trace_bo)
-                       goto fail;
-
-               device->trace_id_ptr = device->ws->buffer_map(device->trace_bo);
-               if (!device->trace_id_ptr)
+               if (!radv_init_trace(device))
                        goto fail;
        }
 
@@ -1196,6 +1289,8 @@ void radv_DestroyDevice(
        VkPipelineCache pc = radv_pipeline_cache_to_handle(device->mem_cache);
        radv_DestroyPipelineCache(radv_device_to_handle(device), pc, NULL);
 
+       radv_destroy_shader_slabs(device);
+
        vk_free(&device->alloc, device);
 }
 
@@ -1278,21 +1373,6 @@ void radv_GetDeviceQueue(
        *pQueue = radv_queue_to_handle(&device->queues[queueFamilyIndex][queueIndex]);
 }
 
-static void radv_dump_trace(struct radv_device *device,
-                           struct radeon_winsys_cs *cs)
-{
-       const char *filename = getenv("RADV_TRACE_FILE");
-       FILE *f = fopen(filename, "w");
-       if (!f) {
-               fprintf(stderr, "Failed to write trace dump to %s\n", filename);
-               return;
-       }
-
-       fprintf(f, "Trace ID: %x\n", *device->trace_id_ptr);
-       device->ws->cs_dump(cs, f, *device->trace_id_ptr);
-       fclose(f);
-}
-
 static void
 fill_geom_tess_rings(struct radv_queue *queue,
                     uint32_t *map,
@@ -1849,6 +1929,89 @@ fail:
        return VK_ERROR_OUT_OF_DEVICE_MEMORY;
 }
 
+static VkResult radv_alloc_sem_counts(struct radv_winsys_sem_counts *counts,
+                                     int num_sems,
+                                     const VkSemaphore *sems,
+                                     bool reset_temp)
+{
+       int syncobj_idx = 0, sem_idx = 0;
+
+       if (num_sems == 0)
+               return VK_SUCCESS;
+       for (uint32_t i = 0; i < num_sems; i++) {
+               RADV_FROM_HANDLE(radv_semaphore, sem, sems[i]);
+
+               if (sem->temp_syncobj || sem->syncobj)
+                       counts->syncobj_count++;
+               else
+                       counts->sem_count++;
+       }
+
+       if (counts->syncobj_count) {
+               counts->syncobj = (uint32_t *)malloc(sizeof(uint32_t) * counts->syncobj_count);
+               if (!counts->syncobj)
+                       return VK_ERROR_OUT_OF_HOST_MEMORY;
+       }
+
+       if (counts->sem_count) {
+               counts->sem = (struct radeon_winsys_sem **)malloc(sizeof(struct radeon_winsys_sem *) * counts->sem_count);
+               if (!counts->sem) {
+                       free(counts->syncobj);
+                       return VK_ERROR_OUT_OF_HOST_MEMORY;
+               }
+       }
+
+       for (uint32_t i = 0; i < num_sems; i++) {
+               RADV_FROM_HANDLE(radv_semaphore, sem, sems[i]);
+
+               if (sem->temp_syncobj) {
+                       counts->syncobj[syncobj_idx++] = sem->temp_syncobj;
+                       if (reset_temp) {
+                               /* after we wait on a temp import - drop it */
+                               sem->temp_syncobj = 0;
+                       }
+               }
+               else if (sem->syncobj)
+                       counts->syncobj[syncobj_idx++] = sem->syncobj;
+               else {
+                       assert(sem->sem);
+                       counts->sem[sem_idx++] = sem->sem;
+               }
+       }
+
+       return VK_SUCCESS;
+}
+
+void radv_free_sem_info(struct radv_winsys_sem_info *sem_info)
+{
+       free(sem_info->wait.syncobj);
+       free(sem_info->wait.sem);
+       free(sem_info->signal.syncobj);
+       free(sem_info->signal.sem);
+}
+
+VkResult radv_alloc_sem_info(struct radv_winsys_sem_info *sem_info,
+                            int num_wait_sems,
+                            const VkSemaphore *wait_sems,
+                            int num_signal_sems,
+                            const VkSemaphore *signal_sems)
+{
+       VkResult ret;
+       memset(sem_info, 0, sizeof(*sem_info));
+
+       ret = radv_alloc_sem_counts(&sem_info->wait, num_wait_sems, wait_sems, true);
+       if (ret)
+               return ret;
+       ret = radv_alloc_sem_counts(&sem_info->signal, num_signal_sems, signal_sems, false);
+       if (ret)
+               radv_free_sem_info(sem_info);
+
+       /* caller can override these */
+       sem_info->cs_emit_wait = true;
+       sem_info->cs_emit_signal = true;
+       return ret;
+}
+
 VkResult radv_QueueSubmit(
        VkQueue                                     _queue,
        uint32_t                                    submitCount,
@@ -1899,16 +2062,22 @@ VkResult radv_QueueSubmit(
                bool do_flush = !i || pSubmits[i].pWaitDstStageMask;
                bool can_patch = !do_flush;
                uint32_t advance;
+               struct radv_winsys_sem_info sem_info;
+
+               result = radv_alloc_sem_info(&sem_info,
+                                            pSubmits[i].waitSemaphoreCount,
+                                            pSubmits[i].pWaitSemaphores,
+                                            pSubmits[i].signalSemaphoreCount,
+                                            pSubmits[i].pSignalSemaphores);
+               if (result != VK_SUCCESS)
+                       return result;
 
                if (!pSubmits[i].commandBufferCount) {
                        if (pSubmits[i].waitSemaphoreCount || pSubmits[i].signalSemaphoreCount) {
                                ret = queue->device->ws->cs_submit(ctx, queue->queue_idx,
                                                                   &queue->device->empty_cs[queue->queue_family_index],
                                                                   1, NULL, NULL,
-                                                                  (struct radeon_winsys_sem **)pSubmits[i].pWaitSemaphores,
-                                                                  pSubmits[i].waitSemaphoreCount,
-                                                                  (struct radeon_winsys_sem **)pSubmits[i].pSignalSemaphores,
-                                                                  pSubmits[i].signalSemaphoreCount,
+                                                                  &sem_info,
                                                                   false, base_fence);
                                if (ret) {
                                        radv_loge("failed to submit CS %d\n", i);
@@ -1916,6 +2085,7 @@ VkResult radv_QueueSubmit(
                                }
                                fence_emitted = true;
                        }
+                       radv_free_sem_info(&sem_info);
                        continue;
                }
 
@@ -1940,18 +2110,16 @@ VkResult radv_QueueSubmit(
                for (uint32_t j = 0; j < pSubmits[i].commandBufferCount + do_flush; j += advance) {
                        advance = MIN2(max_cs_submission,
                                       pSubmits[i].commandBufferCount + do_flush - j);
-                       bool b = j == 0;
-                       bool e = j + advance == pSubmits[i].commandBufferCount + do_flush;
 
                        if (queue->device->trace_bo)
                                *queue->device->trace_id_ptr = 0;
 
+                       sem_info.cs_emit_wait = j == 0;
+                       sem_info.cs_emit_signal = j + advance == pSubmits[i].commandBufferCount + do_flush;
+
                        ret = queue->device->ws->cs_submit(ctx, queue->queue_idx, cs_array + j,
                                                        advance, initial_preamble_cs, continue_preamble_cs,
-                                                       (struct radeon_winsys_sem **)pSubmits[i].pWaitSemaphores,
-                                                       b ? pSubmits[i].waitSemaphoreCount : 0,
-                                                       (struct radeon_winsys_sem **)pSubmits[i].pSignalSemaphores,
-                                                       e ? pSubmits[i].signalSemaphoreCount : 0,
+                                                          &sem_info,
                                                        can_patch, base_fence);
 
                        if (ret) {
@@ -1972,16 +2140,19 @@ VkResult radv_QueueSubmit(
                                }
                        }
                }
+
+               radv_free_sem_info(&sem_info);
                free(cs_array);
        }
 
        if (fence) {
-               if (!fence_emitted)
+               if (!fence_emitted) {
+                       struct radv_winsys_sem_info sem_info = {0};
                        ret = queue->device->ws->cs_submit(ctx, queue->queue_idx,
                                                           &queue->device->empty_cs[queue->queue_family_index],
-                                                          1, NULL, NULL, NULL, 0, NULL, 0,
+                                                          1, NULL, NULL, &sem_info,
                                                           false, base_fence);
-
+               }
                fence->submitted = true;
        }
 
@@ -2076,6 +2247,9 @@ VkResult radv_AllocateMemory(
                *pMem = VK_NULL_HANDLE;
                return VK_SUCCESS;
        }
+
+       const VkImportMemoryFdInfoKHR *import_info =
+               vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
        const VkMemoryDedicatedAllocateInfoKHR *dedicate_info =
                vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO_KHR);
 
@@ -2092,6 +2266,20 @@ VkResult radv_AllocateMemory(
                mem->buffer = NULL;
        }
 
+       if (import_info) {
+               assert(import_info->handleType ==
+                      VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
+               mem->bo = device->ws->buffer_from_fd(device->ws, import_info->fd,
+                                                    NULL, NULL);
+               if (!mem->bo) {
+                       result = VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
+                       goto fail;
+               } else {
+                       close(import_info->fd);
+                       goto out_success;
+               }
+       }
+
        uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
        if (pAllocateInfo->memoryTypeIndex == RADV_MEM_TYPE_GTT_WRITE_COMBINE ||
            pAllocateInfo->memoryTypeIndex == RADV_MEM_TYPE_GTT_CACHED)
@@ -2115,7 +2303,7 @@ VkResult radv_AllocateMemory(
                goto fail;
        }
        mem->type_index = pAllocateInfo->memoryTypeIndex;
-
+out_success:
        *pMem = radv_device_memory_to_handle(mem);
 
        return VK_SUCCESS;
@@ -2258,12 +2446,14 @@ void radv_GetImageMemoryRequirements2KHR(
        radv_GetImageMemoryRequirements(device, pInfo->image,
                                         &pMemoryRequirements->memoryRequirements);
 
+       RADV_FROM_HANDLE(radv_image, image, pInfo->image);
+
        vk_foreach_struct(ext, pMemoryRequirements->pNext) {
                switch (ext->sType) {
                case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR: {
                        VkMemoryDedicatedRequirementsKHR *req =
                                       (VkMemoryDedicatedRequirementsKHR *) ext;
-                       req->requiresDedicatedAllocation = false;
+                       req->requiresDedicatedAllocation = image->shareable;
                        req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
                        break;
                }
@@ -2392,6 +2582,7 @@ radv_sparse_image_opaque_bind_memory(struct radv_device *device,
        bool fence_emitted = false;
 
        for (uint32_t i = 0; i < bindInfoCount; ++i) {
+               struct radv_winsys_sem_info sem_info;
                for (uint32_t j = 0; j < pBindInfo[i].bufferBindCount; ++j) {
                        radv_sparse_buffer_bind_memory(queue->device,
                                                       pBindInfo[i].pBufferBinds + j);
@@ -2402,19 +2593,28 @@ radv_sparse_image_opaque_bind_memory(struct radv_device *device,
                                                             pBindInfo[i].pImageOpaqueBinds + j);
                }
 
+               VkResult result;
+               result = radv_alloc_sem_info(&sem_info,
+                                            pBindInfo[i].waitSemaphoreCount,
+                                            pBindInfo[i].pWaitSemaphores,
+                                            pBindInfo[i].signalSemaphoreCount,
+                                            pBindInfo[i].pSignalSemaphores);
+               if (result != VK_SUCCESS)
+                       return result;
+
                if (pBindInfo[i].waitSemaphoreCount || pBindInfo[i].signalSemaphoreCount) {
                        queue->device->ws->cs_submit(queue->hw_ctx, queue->queue_idx,
                                                     &queue->device->empty_cs[queue->queue_family_index],
                                                     1, NULL, NULL,
-                                                    (struct radeon_winsys_sem **)pBindInfo[i].pWaitSemaphores,
-                                                    pBindInfo[i].waitSemaphoreCount,
-                                                    (struct radeon_winsys_sem **)pBindInfo[i].pSignalSemaphores,
-                                                    pBindInfo[i].signalSemaphoreCount,
+                                                    &sem_info,
                                                     false, base_fence);
                        fence_emitted = true;
                        if (fence)
                                fence->submitted = true;
                }
+
+               radv_free_sem_info(&sem_info);
+
        }
 
        if (fence && !fence_emitted) {
@@ -2551,13 +2751,38 @@ VkResult radv_CreateSemaphore(
        VkSemaphore*                                pSemaphore)
 {
        RADV_FROM_HANDLE(radv_device, device, _device);
-       struct radeon_winsys_sem *sem;
+       const VkExportSemaphoreCreateInfoKHR *export =
+               vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO_KHR);
+       VkExternalSemaphoreHandleTypeFlagsKHR handleTypes =
+               export ? export->handleTypes : 0;
 
-       sem = device->ws->create_sem(device->ws);
+       struct radv_semaphore *sem = vk_alloc2(&device->alloc, pAllocator,
+                                              sizeof(*sem), 8,
+                                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
        if (!sem)
                return VK_ERROR_OUT_OF_HOST_MEMORY;
 
-       *pSemaphore = radeon_winsys_sem_to_handle(sem);
+       sem->temp_syncobj = 0;
+       /* create a syncobject if we are going to export this semaphore */
+       if (handleTypes) {
+               assert (device->physical_device->rad_info.has_syncobj);
+               assert (handleTypes == VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
+               int ret = device->ws->create_syncobj(device->ws, &sem->syncobj);
+               if (ret) {
+                       vk_free2(&device->alloc, pAllocator, sem);
+                       return VK_ERROR_OUT_OF_HOST_MEMORY;
+               }
+               sem->sem = NULL;
+       } else {
+               sem->sem = device->ws->create_sem(device->ws);
+               if (!sem->sem) {
+                       vk_free2(&device->alloc, pAllocator, sem);
+                       return VK_ERROR_OUT_OF_HOST_MEMORY;
+               }
+               sem->syncobj = 0;
+       }
+
+       *pSemaphore = radv_semaphore_to_handle(sem);
        return VK_SUCCESS;
 }
 
@@ -2567,11 +2792,15 @@ void radv_DestroySemaphore(
        const VkAllocationCallbacks*                pAllocator)
 {
        RADV_FROM_HANDLE(radv_device, device, _device);
-       RADV_FROM_HANDLE(radeon_winsys_sem, sem, _semaphore);
+       RADV_FROM_HANDLE(radv_semaphore, sem, _semaphore);
        if (!_semaphore)
                return;
 
-       device->ws->destroy_sem(sem);
+       if (sem->syncobj)
+               device->ws->destroy_syncobj(device->ws, sem->syncobj);
+       else
+               device->ws->destroy_sem(sem->sem);
+       vk_free2(&device->alloc, pAllocator, sem);
 }
 
 VkResult radv_CreateEvent(
@@ -2736,6 +2965,8 @@ radv_initialise_color_surface(struct radv_device *device,
 
        va = device->ws->buffer_get_va(iview->bo) + iview->image->offset;
 
+       cb->cb_color_base = va >> 8;
+
        if (device->physical_device->rad_info.chip_class >= GFX9) {
                struct gfx9_surf_meta_flags meta;
                if (iview->image->dcc_offset)
@@ -2748,12 +2979,15 @@ radv_initialise_color_surface(struct radv_device *device,
                        S_028C74_RB_ALIGNED(meta.rb_aligned) |
                        S_028C74_PIPE_ALIGNED(meta.pipe_aligned);
 
-               va += iview->image->surface.u.gfx9.surf_offset >> 8;
+               cb->cb_color_base += iview->image->surface.u.gfx9.surf_offset >> 8;
+               cb->cb_color_base |= iview->image->surface.tile_swizzle;
        } else {
                const struct legacy_surf_level *level_info = &surf->u.legacy.level[iview->base_mip];
                unsigned pitch_tile_max, slice_tile_max, tile_mode_index;
 
-               va += level_info->offset;
+               cb->cb_color_base += level_info->offset >> 8;
+               if (level_info->mode == RADEON_SURF_MODE_2D)
+                       cb->cb_color_base |= iview->image->surface.tile_swizzle;
 
                pitch_tile_max = level_info->nblk_x / 8 - 1;
                slice_tile_max = (level_info->nblk_x * level_info->nblk_y) / 64 - 1;
@@ -2780,8 +3014,6 @@ radv_initialise_color_surface(struct radv_device *device,
                }
        }
 
-       cb->cb_color_base = va >> 8;
-
        /* CMASK variables */
        va = device->ws->buffer_get_va(iview->bo) + iview->image->offset;
        va += iview->image->cmask.offset;
@@ -2790,6 +3022,7 @@ radv_initialise_color_surface(struct radv_device *device,
        va = device->ws->buffer_get_va(iview->bo) + iview->image->offset;
        va += iview->image->dcc_offset;
        cb->cb_dcc_base = va >> 8;
+       cb->cb_dcc_base |= iview->image->surface.tile_swizzle;
 
        uint32_t max_slice = radv_surface_layer_count(iview);
        cb->cb_color_view = S_028C6C_SLICE_START(iview->base_layer) |
@@ -2805,6 +3038,7 @@ radv_initialise_color_surface(struct radv_device *device,
        if (iview->image->fmask.size) {
                va = device->ws->buffer_get_va(iview->bo) + iview->image->offset + iview->image->fmask.offset;
                cb->cb_color_fmask = va >> 8;
+               cb->cb_color_fmask |= iview->image->fmask.tile_swizzle;
        } else {
                cb->cb_color_fmask = cb->cb_color_base;
        }
@@ -2851,9 +3085,13 @@ radv_initialise_color_surface(struct radv_device *device,
                                    format != V_028C70_COLOR_24_8) |
                S_028C70_NUMBER_TYPE(ntype) |
                S_028C70_ENDIAN(endian);
-       if (iview->image->info.samples > 1)
-               if (iview->image->fmask.size)
-                       cb->cb_color_info |= S_028C70_COMPRESSION(1);
+       if ((iview->image->info.samples > 1) && iview->image->fmask.size) {
+               cb->cb_color_info |= S_028C70_COMPRESSION(1);
+               if (device->physical_device->rad_info.chip_class == SI) {
+                       unsigned fmask_bankh = util_logbase2(iview->image->fmask.bank_height);
+                       cb->cb_color_attrib |= S_028C74_FMASK_BANK_HEIGHT(fmask_bankh);
+               }
+       }
 
        if (iview->image->cmask.size &&
            !(device->debug_flags & RADV_DEBUG_NO_FAST_CLEARS))
@@ -2889,9 +3127,9 @@ radv_initialise_color_surface(struct radv_device *device,
                cb->cb_color_view |= S_028C6C_MIP_LEVEL(iview->base_mip);
                cb->cb_color_attrib |= S_028C74_MIP0_DEPTH(mip0_depth) |
                        S_028C74_RESOURCE_TYPE(iview->image->surface.u.gfx9.resource_type);
-               cb->cb_color_attrib2 = S_028C68_MIP0_WIDTH(iview->image->info.width - 1) |
-                       S_028C68_MIP0_HEIGHT(iview->image->info.height - 1) |
-                       S_028C68_MAX_MIP(iview->image->info.levels);
+               cb->cb_color_attrib2 = S_028C68_MIP0_WIDTH(iview->extent.width - 1) |
+                       S_028C68_MIP0_HEIGHT(iview->extent.height - 1) |
+                       S_028C68_MAX_MIP(iview->image->info.levels - 1);
 
                cb->gfx9_epitch = S_0287A0_EPITCH(iview->image->surface.u.gfx9.surf.epitch);
 
@@ -3020,6 +3258,8 @@ radv_initialise_ds_surface(struct radv_device *device,
                        ds->db_z_info |= S_028040_TILE_MODE_INDEX(tile_mode_index);
                        tile_mode_index = si_tile_mode_index(iview->image, level, true);
                        ds->db_stencil_info |= S_028044_TILE_MODE_INDEX(tile_mode_index);
+                       if (stencil_only)
+                               ds->db_z_info |= S_028040_TILE_MODE_INDEX(tile_mode_index);
                }
 
                ds->db_depth_size = S_028058_PITCH_TILE_MAX((level_info->nblk_x / 8) - 1) |
@@ -3318,3 +3558,94 @@ vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
        *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
        return VK_SUCCESS;
 }
+
+VkResult radv_GetMemoryFdKHR(VkDevice _device,
+                            const VkMemoryGetFdInfoKHR *pGetFdInfo,
+                            int *pFD)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       RADV_FROM_HANDLE(radv_device_memory, memory, pGetFdInfo->memory);
+
+       assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
+
+       /* We support only one handle type. */
+       assert(pGetFdInfo->handleType ==
+              VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
+
+       bool ret = radv_get_memory_fd(device, memory, pFD);
+       if (ret == false)
+               return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+       return VK_SUCCESS;
+}
+
+VkResult radv_GetMemoryFdPropertiesKHR(VkDevice _device,
+                                      VkExternalMemoryHandleTypeFlagBitsKHR handleType,
+                                      int fd,
+                                      VkMemoryFdPropertiesKHR *pMemoryFdProperties)
+{
+   /* The valid usage section for this function says:
+    *
+    *    "handleType must not be one of the handle types defined as opaque."
+    *
+    * Since we only handle opaque handles for now, there are no FD properties.
+    */
+   return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
+}
+
+VkResult radv_ImportSemaphoreFdKHR(VkDevice _device,
+                                  const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       RADV_FROM_HANDLE(radv_semaphore, sem, pImportSemaphoreFdInfo->semaphore);
+       uint32_t syncobj_handle = 0;
+       assert(pImportSemaphoreFdInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
+
+       int ret = device->ws->import_syncobj(device->ws, pImportSemaphoreFdInfo->fd, &syncobj_handle);
+       if (ret != 0)
+               return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
+
+       if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR) {
+               sem->temp_syncobj = syncobj_handle;
+       } else {
+               sem->syncobj = syncobj_handle;
+       }
+       close(pImportSemaphoreFdInfo->fd);
+       return VK_SUCCESS;
+}
+
+VkResult radv_GetSemaphoreFdKHR(VkDevice _device,
+                               const VkSemaphoreGetFdInfoKHR *pGetFdInfo,
+                               int *pFd)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       RADV_FROM_HANDLE(radv_semaphore, sem, pGetFdInfo->semaphore);
+       int ret;
+       uint32_t syncobj_handle;
+
+       assert(pGetFdInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
+       if (sem->temp_syncobj)
+               syncobj_handle = sem->temp_syncobj;
+       else
+               syncobj_handle = sem->syncobj;
+       ret = device->ws->export_syncobj(device->ws, syncobj_handle, pFd);
+       if (ret)
+               return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
+       return VK_SUCCESS;
+}
+
+void radv_GetPhysicalDeviceExternalSemaphorePropertiesKHR(
+       VkPhysicalDevice                            physicalDevice,
+       const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
+       VkExternalSemaphorePropertiesKHR*           pExternalSemaphoreProperties)
+{
+       if (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) {
+               pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+               pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+               pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
+                       VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
+       } else {
+               pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
+               pExternalSemaphoreProperties->compatibleHandleTypes = 0;
+               pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
+       }
+}