radv: Implement VK_EXT_discard_rectangles.
[mesa.git] / src / amd / vulkan / radv_device.c
index fc9fb59f9916db1fb95df902022c9411ede31cdf..baffa41d31694301e74b326b3685c13a86696ea3 100644 (file)
@@ -263,6 +263,12 @@ radv_physical_device_init(struct radv_physical_device *device,
         */
        device->has_clear_state = device->rad_info.chip_class >= CIK;
 
+       device->cpdma_prefetch_writes_memory = device->rad_info.chip_class <= VI;
+
+       /* Vega10/Raven need a special workaround for a hardware bug. */
+       device->has_scissor_bug = device->rad_info.family == CHIP_VEGA10 ||
+                                 device->rad_info.family == CHIP_RAVEN;
+
        radv_physical_device_init_mem_types(device);
 
        result = radv_init_wsi(device);
@@ -343,6 +349,8 @@ radv_get_debug_option_name(int id)
 static const struct debug_control radv_perftest_options[] = {
        {"nobatchchain", RADV_PERFTEST_NO_BATCHCHAIN},
        {"sisched", RADV_PERFTEST_SISCHED},
+       {"localbos", RADV_PERFTEST_LOCAL_BOS},
+       {"binning", RADV_PERFTEST_BINNING},
        {NULL, 0}
 };
 
@@ -786,6 +794,12 @@ void radv_GetPhysicalDeviceProperties2KHR(
                        properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR;
                        break;
                }
+               case  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT: {
+                       VkPhysicalDeviceDiscardRectanglePropertiesEXT *properties =
+                           (VkPhysicalDeviceDiscardRectanglePropertiesEXT*)ext;
+                       properties->maxDiscardRectangles = MAX_DISCARD_RECTANGLES;
+                       break;
+               }
                default:
                        break;
                }
@@ -1079,6 +1093,13 @@ VkResult radv_CreateDevice(
                }
        }
 
+       device->pbb_allowed = device->physical_device->rad_info.chip_class >= GFX9 &&
+                             (device->instance->perftest_flags & RADV_PERFTEST_BINNING);
+
+       /* Disabled and not implemented for now. */
+       device->dfsm_allowed = device->pbb_allowed && false;
+
+
 #if HAVE_LLVM < 0x0400
        device->llvm_supports_spill = false;
 #else
@@ -1594,7 +1615,9 @@ radv_get_preamble_cs(struct radv_queue *queue,
                                                                 size,
                                                                 4096,
                                                                 RADEON_DOMAIN_VRAM,
-                                                                RADEON_FLAG_CPU_ACCESS|RADEON_FLAG_NO_INTERPROCESS_SHARING);
+                                                                RADEON_FLAG_CPU_ACCESS |
+                                                                RADEON_FLAG_NO_INTERPROCESS_SHARING |
+                                                                RADEON_FLAG_READ_ONLY);
                if (!descriptor_bo)
                        goto fail;
        } else
@@ -2825,7 +2848,6 @@ VkResult radv_CreateSemaphore(
        /* 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);
@@ -3002,9 +3024,9 @@ si_tile_mode_index(const struct radv_image *image, unsigned level, bool stencil)
                return image->surface.u.legacy.tiling_index[level];
 }
 
-static uint32_t radv_surface_layer_count(struct radv_image_view *iview)
+static uint32_t radv_surface_max_layer_count(struct radv_image_view *iview)
 {
-       return iview->type == VK_IMAGE_VIEW_TYPE_3D ? iview->extent.depth : iview->layer_count;
+       return iview->type == VK_IMAGE_VIEW_TYPE_3D ? iview->extent.depth : (iview->base_layer + iview->layer_count);
 }
 
 static void
@@ -3085,9 +3107,9 @@ radv_initialise_color_surface(struct radv_device *device,
        cb->cb_dcc_base = va >> 8;
        cb->cb_dcc_base |= iview->image->surface.tile_swizzle;
 
-       uint32_t max_slice = radv_surface_layer_count(iview);
+       uint32_t max_slice = radv_surface_max_layer_count(iview) - 1;
        cb->cb_color_view = S_028C6C_SLICE_START(iview->base_layer) |
-               S_028C6C_SLICE_MAX(iview->base_layer + max_slice - 1);
+               S_028C6C_SLICE_MAX(max_slice);
 
        if (iview->image->info.samples > 1) {
                unsigned log_samples = util_logbase2(iview->image->info.samples);
@@ -3162,16 +3184,36 @@ radv_initialise_color_surface(struct radv_device *device,
                cb->cb_color_info |= S_028C70_DCC_ENABLE(1);
 
        if (device->physical_device->rad_info.chip_class >= VI) {
-               unsigned max_uncompressed_block_size = 2;
+               unsigned max_uncompressed_block_size = V_028C78_MAX_BLOCK_SIZE_256B;
+               unsigned min_compressed_block_size = V_028C78_MIN_BLOCK_SIZE_32B;
+               unsigned independent_64b_blocks = 0;
+               unsigned max_compressed_block_size;
+
+               /* amdvlk: [min-compressed-block-size] should be set to 32 for dGPU and
+                  64 for APU because all of our APUs to date use DIMMs which have
+                  a request granularity size of 64B while all other chips have a
+                  32B request size */
+               if (!device->physical_device->rad_info.has_dedicated_vram)
+                       min_compressed_block_size = V_028C78_MIN_BLOCK_SIZE_64B;
+
                if (iview->image->info.samples > 1) {
                        if (iview->image->surface.bpe == 1)
-                               max_uncompressed_block_size = 0;
+                               max_uncompressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
                        else if (iview->image->surface.bpe == 2)
-                               max_uncompressed_block_size = 1;
+                               max_uncompressed_block_size = V_028C78_MAX_BLOCK_SIZE_128B;
                }
 
+               if (iview->image->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+                                          VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
+                       independent_64b_blocks = 1;
+                       max_compressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B;
+               } else
+                       max_compressed_block_size = max_uncompressed_block_size;
+
                cb->cb_dcc_control = S_028C78_MAX_UNCOMPRESSED_BLOCK_SIZE(max_uncompressed_block_size) |
-                       S_028C78_INDEPENDENT_64B_BLOCKS(1);
+                       S_028C78_MAX_COMPRESSED_BLOCK_SIZE(max_compressed_block_size) |
+                       S_028C78_MIN_COMPRESSED_BLOCK_SIZE(min_compressed_block_size) |
+                       S_028C78_INDEPENDENT_64B_BLOCKS(independent_64b_blocks);
        }
 
        /* This must be set for fast clear to work without FMASK. */
@@ -3232,9 +3274,9 @@ radv_initialise_ds_surface(struct radv_device *device,
        stencil_format = iview->image->surface.has_stencil ?
                V_028044_STENCIL_8 : V_028044_STENCIL_INVALID;
 
-       uint32_t max_slice = radv_surface_layer_count(iview);
+       uint32_t max_slice = radv_surface_max_layer_count(iview) - 1;
        ds->db_depth_view = S_028008_SLICE_START(iview->base_layer) |
-               S_028008_SLICE_MAX(iview->base_layer + max_slice - 1);
+               S_028008_SLICE_MAX(max_slice);
 
        ds->db_htile_data_base = 0;
        ds->db_htile_surface = 0;
@@ -3398,7 +3440,7 @@ VkResult radv_CreateFramebuffer(
                }
                framebuffer->width = MIN2(framebuffer->width, iview->extent.width);
                framebuffer->height = MIN2(framebuffer->height, iview->extent.height);
-               framebuffer->layers = MIN2(framebuffer->layers, radv_surface_layer_count(iview));
+               framebuffer->layers = MIN2(framebuffer->layers, radv_surface_max_layer_count(iview));
        }
 
        *pFramebuffer = radv_framebuffer_to_handle(framebuffer);
@@ -3683,18 +3725,59 @@ VkResult radv_GetMemoryFdPropertiesKHR(VkDevice _device,
    }
 }
 
+static VkResult radv_import_opaque_fd(struct radv_device *device,
+                                      int fd,
+                                      uint32_t *syncobj)
+{
+       uint32_t syncobj_handle = 0;
+       int ret = device->ws->import_syncobj(device->ws, fd, &syncobj_handle);
+       if (ret != 0)
+               return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
+
+       if (*syncobj)
+               device->ws->destroy_syncobj(device->ws, *syncobj);
+
+       *syncobj = syncobj_handle;
+       close(fd);
+
+       return VK_SUCCESS;
+}
+
+static VkResult radv_import_sync_fd(struct radv_device *device,
+                                    int fd,
+                                    uint32_t *syncobj)
+{
+       /* If we create a syncobj we do it locally so that if we have an error, we don't
+        * leave a syncobj in an undetermined state in the fence. */
+       uint32_t syncobj_handle =  *syncobj;
+       if (!syncobj_handle) {
+               int ret = device->ws->create_syncobj(device->ws, &syncobj_handle);
+               if (ret) {
+                       return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
+               }
+       }
+
+       if (fd == -1) {
+               device->ws->signal_syncobj(device->ws, syncobj_handle);
+       } else {
+               int ret = device->ws->import_syncobj_from_sync_file(device->ws, syncobj_handle, fd);
+       if (ret != 0)
+               return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
+       }
+
+       *syncobj = syncobj_handle;
+       if (fd != -1)
+               close(fd);
+
+       return VK_SUCCESS;
+}
+
 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;
        uint32_t *syncobj_dst = NULL;
-       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(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
 
        if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR) {
                syncobj_dst = &sem->temp_syncobj;
@@ -3702,12 +3785,14 @@ VkResult radv_ImportSemaphoreFdKHR(VkDevice _device,
                syncobj_dst = &sem->syncobj;
        }
 
-       if (*syncobj_dst)
-               device->ws->destroy_syncobj(device->ws, *syncobj_dst);
-
-       *syncobj_dst = syncobj_handle;
-       close(pImportSemaphoreFdInfo->fd);
-       return VK_SUCCESS;
+       switch(pImportSemaphoreFdInfo->handleType) {
+               case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
+                       return radv_import_opaque_fd(device, pImportSemaphoreFdInfo->fd, syncobj_dst);
+               case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
+                       return radv_import_sync_fd(device, pImportSemaphoreFdInfo->fd, syncobj_dst);
+               default:
+                       unreachable("Unhandled semaphore handle type");
+       }
 }
 
 VkResult radv_GetSemaphoreFdKHR(VkDevice _device,
@@ -3719,12 +3804,22 @@ VkResult radv_GetSemaphoreFdKHR(VkDevice _device,
        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);
+
+       switch(pGetFdInfo->handleType) {
+       case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
+               ret = device->ws->export_syncobj(device->ws, syncobj_handle, pFd);
+               break;
+       case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
+               ret = device->ws->export_syncobj_to_sync_file(device->ws, syncobj_handle, pFd);
+               break;
+       default:
+               unreachable("Unhandled semaphore handle type");
+       }
+
        if (ret)
                return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
        return VK_SUCCESS;
@@ -3735,7 +3830,17 @@ void radv_GetPhysicalDeviceExternalSemaphorePropertiesKHR(
        const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
        VkExternalSemaphorePropertiesKHR*           pExternalSemaphoreProperties)
 {
-       if (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) {
+       RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice);
+
+       /* Require has_syncobj_wait_for_submit for the syncobj signal ioctl introduced at virtually the same time */
+       if (pdevice->rad_info.has_syncobj_wait_for_submit &&
+           (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR || 
+            pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR)) {
+               pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
+               pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
+               pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
+                       VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
+       } else 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 |
@@ -3746,3 +3851,78 @@ void radv_GetPhysicalDeviceExternalSemaphorePropertiesKHR(
                pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
        }
 }
+
+VkResult radv_ImportFenceFdKHR(VkDevice _device,
+                                  const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       RADV_FROM_HANDLE(radv_fence, fence, pImportFenceFdInfo->fence);
+       uint32_t *syncobj_dst = NULL;
+
+
+       if (pImportFenceFdInfo->flags & VK_FENCE_IMPORT_TEMPORARY_BIT_KHR) {
+               syncobj_dst = &fence->temp_syncobj;
+       } else {
+               syncobj_dst = &fence->syncobj;
+       }
+
+       switch(pImportFenceFdInfo->handleType) {
+               case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
+                       return radv_import_opaque_fd(device, pImportFenceFdInfo->fd, syncobj_dst);
+               case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
+                       return radv_import_sync_fd(device, pImportFenceFdInfo->fd, syncobj_dst);
+               default:
+                       unreachable("Unhandled fence handle type");
+       }
+}
+
+VkResult radv_GetFenceFdKHR(VkDevice _device,
+                               const VkFenceGetFdInfoKHR *pGetFdInfo,
+                               int *pFd)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       RADV_FROM_HANDLE(radv_fence, fence, pGetFdInfo->fence);
+       int ret;
+       uint32_t syncobj_handle;
+
+       if (fence->temp_syncobj)
+               syncobj_handle = fence->temp_syncobj;
+       else
+               syncobj_handle = fence->syncobj;
+
+       switch(pGetFdInfo->handleType) {
+       case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
+               ret = device->ws->export_syncobj(device->ws, syncobj_handle, pFd);
+               break;
+       case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
+               ret = device->ws->export_syncobj_to_sync_file(device->ws, syncobj_handle, pFd);
+               break;
+       default:
+               unreachable("Unhandled fence handle type");
+       }
+
+       if (ret)
+               return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
+       return VK_SUCCESS;
+}
+
+void radv_GetPhysicalDeviceExternalFencePropertiesKHR(
+       VkPhysicalDevice                            physicalDevice,
+       const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo,
+       VkExternalFencePropertiesKHR*           pExternalFenceProperties)
+{
+       RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice);
+
+       if (pdevice->rad_info.has_syncobj_wait_for_submit &&
+           (pExternalFenceInfo->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR || 
+            pExternalFenceInfo->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR)) {
+               pExternalFenceProperties->exportFromImportedHandleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR | VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
+               pExternalFenceProperties->compatibleHandleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR | VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
+               pExternalFenceProperties->externalFenceFeatures = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR |
+                       VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
+       } else {
+               pExternalFenceProperties->exportFromImportedHandleTypes = 0;
+               pExternalFenceProperties->compatibleHandleTypes = 0;
+               pExternalFenceProperties->externalFenceFeatures = 0;
+       }
+}