radv: require DRM 3.35+

Linux Kernel 4.15+ is now required for RADV, this kernel has been
released 3 years ago and should be in most modern distros.

This allows us to remove a lot of legacy code for fence/semaphore.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9800>
This commit is contained in:
Samuel Pitoiset 2021-03-24 09:54:28 +01:00 committed by Marge Bot
parent fb6814cd91
commit 1df4f11eb5
11 changed files with 57 additions and 476 deletions

View File

@ -616,9 +616,7 @@ bool ac_query_gpu_info(int fd, void *dev_p, struct radeon_info *info,
info->has_userptr = true;
info->has_syncobj = has_syncobj(fd);
info->has_timeline_syncobj = has_timeline_syncobj(fd);
info->has_syncobj_wait_for_submit = info->has_syncobj && info->drm_minor >= 20;
info->has_fence_to_handle = info->has_syncobj && info->drm_minor >= 21;
info->has_ctx_priority = info->drm_minor >= 22;
info->has_local_buffers = info->drm_minor >= 20;
info->kernel_flushes_hdp_before_ib = true;
info->htile_cmask_support_1d_tiling = true;
@ -1107,10 +1105,8 @@ void ac_print_gpu_info(struct radeon_info *info, FILE *f)
fprintf(f, " drm = %i.%i.%i\n", info->drm_major, info->drm_minor, info->drm_patchlevel);
fprintf(f, " has_userptr = %i\n", info->has_userptr);
fprintf(f, " has_syncobj = %u\n", info->has_syncobj);
fprintf(f, " has_syncobj_wait_for_submit = %u\n", info->has_syncobj_wait_for_submit);
fprintf(f, " has_timeline_syncobj = %u\n", info->has_timeline_syncobj);
fprintf(f, " has_fence_to_handle = %u\n", info->has_fence_to_handle);
fprintf(f, " has_ctx_priority = %u\n", info->has_ctx_priority);
fprintf(f, " has_local_buffers = %u\n", info->has_local_buffers);
fprintf(f, " kernel_flushes_hdp_before_ib = %u\n", info->kernel_flushes_hdp_before_ib);
fprintf(f, " htile_cmask_support_1d_tiling = %u\n", info->htile_cmask_support_1d_tiling);

View File

@ -143,10 +143,8 @@ struct radeon_info {
bool is_amdgpu;
bool has_userptr;
bool has_syncobj;
bool has_syncobj_wait_for_submit;
bool has_timeline_syncobj;
bool has_fence_to_handle;
bool has_ctx_priority;
bool has_local_buffers;
bool kernel_flushes_hdp_before_ib;
bool htile_cmask_support_1d_tiling;

View File

@ -127,12 +127,6 @@ radv_dump_debug_registers(struct radv_device *device, FILE *f)
fprintf(f, "Memory-mapped registers:\n");
radv_dump_mmapped_reg(device, f, R_008010_GRBM_STATUS);
/* No other registers can be read on DRM < 3.1.0. */
if (info->drm_minor < 1) {
fprintf(f, "\n");
return;
}
radv_dump_mmapped_reg(device, f, R_008008_GRBM_STATUS2);
radv_dump_mmapped_reg(device, f, R_008014_GRBM_STATUS_SE0);
radv_dump_mmapped_reg(device, f, R_008018_GRBM_STATUS_SE1);

View File

@ -385,12 +385,12 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
.KHR_device_group = true,
.KHR_draw_indirect_count = true,
.KHR_driver_properties = true,
.KHR_external_fence = device->rad_info.has_syncobj_wait_for_submit,
.KHR_external_fence_fd = device->rad_info.has_syncobj_wait_for_submit,
.KHR_external_fence = true,
.KHR_external_fence_fd = true,
.KHR_external_memory = true,
.KHR_external_memory_fd = true,
.KHR_external_semaphore = device->rad_info.has_syncobj,
.KHR_external_semaphore_fd = device->rad_info.has_syncobj,
.KHR_external_semaphore = true,
.KHR_external_semaphore_fd = true,
.KHR_fragment_shading_rate = device->rad_info.chip_class >= GFX10_3,
.KHR_get_memory_requirements2 = true,
.KHR_image_format_list = true,
@ -422,7 +422,7 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
.KHR_swapchain = true,
.KHR_swapchain_mutable_format = true,
#endif
.KHR_timeline_semaphore = device->rad_info.has_syncobj_wait_for_submit,
.KHR_timeline_semaphore = true,
.KHR_uniform_buffer_standard_layout = true,
.KHR_variable_pointers = true,
.KHR_vulkan_memory_model = true,
@ -440,12 +440,12 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
.EXT_descriptor_indexing = true,
.EXT_discard_rectangles = true,
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
.EXT_display_control = device->rad_info.has_syncobj_wait_for_submit,
.EXT_display_control = true,
#endif
.EXT_extended_dynamic_state = true,
.EXT_external_memory_dma_buf = true,
.EXT_external_memory_host = device->rad_info.has_userptr,
.EXT_global_priority = device->rad_info.has_ctx_priority,
.EXT_global_priority = true,
.EXT_host_query_reset = true,
.EXT_image_drm_format_modifier = device->rad_info.chip_class >= GFX9,
.EXT_image_robustness = true,
@ -495,9 +495,8 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
.AMD_shader_trinary_minmax = true,
.AMD_texture_gather_bias_lod = true,
#ifdef ANDROID
.ANDROID_external_memory_android_hardware_buffer = RADV_SUPPORT_ANDROID_HARDWARE_BUFFER &&
device->rad_info.has_syncobj_wait_for_submit,
.ANDROID_native_buffer = device->rad_info.has_syncobj_wait_for_submit,
.ANDROID_external_memory_android_hardware_buffer = RADV_SUPPORT_ANDROID_HARDWARE_BUFFER,
.ANDROID_native_buffer = true,
#endif
.GOOGLE_decorate_string = true,
.GOOGLE_hlsl_functionality1 = true,
@ -1256,7 +1255,7 @@ radv_get_physical_device_features_1_2(struct radv_physical_device *pdevice,
f->shaderSubgroupExtendedTypes = true;
f->separateDepthStencilLayouts = true;
f->hostQueryReset = true;
f->timelineSemaphore = pdevice->rad_info.has_syncobj_wait_for_submit;
f->timelineSemaphore = true,
f->bufferDeviceAddress = true;
f->bufferDeviceAddressCaptureReplay = false;
f->bufferDeviceAddressMultiDevice = false;
@ -2894,8 +2893,6 @@ VkResult radv_CreateDevice(
const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority =
vk_find_struct_const(queue_create->pNext, DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT);
assert(!global_priority || device->physical_device->rad_info.has_ctx_priority);
device->queues[qfi] = vk_alloc(&device->vk.alloc,
queue_create->queueCount * sizeof(struct radv_queue), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
if (!device->queues[qfi]) {
@ -2923,8 +2920,6 @@ VkResult radv_CreateDevice(
device->dfsm_allowed = device->pbb_allowed &&
(device->instance->perftest_flags & RADV_PERFTEST_DFSM);
device->always_use_syncobj = device->physical_device->rad_info.has_syncobj_wait_for_submit;
/* The maximum number of scratch waves. Scratch space isn't divided
* evenly between CUs. The number is only a function of the number of CUs.
* We can decrease the constant to decrease the scratch buffer size.
@ -4079,7 +4074,7 @@ static VkResult radv_alloc_sem_counts(struct radv_device *device,
VkFence _fence,
bool is_signal)
{
int syncobj_idx = 0, non_reset_idx = 0, sem_idx = 0, timeline_idx = 0;
int syncobj_idx = 0, non_reset_idx = 0, timeline_idx = 0;
if (num_sems == 0 && _fence == VK_NULL_HANDLE)
return VK_SUCCESS;
@ -4090,9 +4085,6 @@ static VkResult radv_alloc_sem_counts(struct radv_device *device,
counts->syncobj_count++;
counts->syncobj_reset_count++;
break;
case RADV_SEMAPHORE_WINSYS:
counts->sem_count++;
break;
case RADV_SEMAPHORE_NONE:
break;
case RADV_SEMAPHORE_TIMELINE:
@ -4123,14 +4115,6 @@ static VkResult radv_alloc_sem_counts(struct radv_device *device,
counts->syncobj = (uint32_t*)(counts->points + counts->timeline_syncobj_count);
}
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(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
}
}
non_reset_idx = counts->syncobj_reset_count;
for (uint32_t i = 0; i < num_sems; i++) {
@ -4141,9 +4125,6 @@ static VkResult radv_alloc_sem_counts(struct radv_device *device,
case RADV_SEMAPHORE_SYNCOBJ:
counts->syncobj[syncobj_idx++] = sems[i]->syncobj;
break;
case RADV_SEMAPHORE_WINSYS:
counts->sem[sem_idx++] = sems[i]->ws_sem;
break;
case RADV_SEMAPHORE_TIMELINE: {
mtx_lock(&sems[i]->timeline.mutex);
struct radv_timeline_point *point = NULL;
@ -4192,9 +4173,7 @@ static void
radv_free_sem_info(struct radv_winsys_sem_info *sem_info)
{
free(sem_info->wait.points);
free(sem_info->wait.sem);
free(sem_info->signal.points);
free(sem_info->signal.sem);
}
@ -4693,11 +4672,9 @@ static VkResult
radv_queue_submit_deferred(struct radv_deferred_queue_submission *submission,
struct list_head *processing_list)
{
RADV_FROM_HANDLE(radv_fence, fence, submission->fence);
struct radv_queue *queue = submission->queue;
struct radeon_winsys_ctx *ctx = queue->hw_ctx;
uint32_t max_cs_submission = queue->device->trace_bo ? 1 : RADV_MAX_IBS_PER_SUBMIT;
struct radeon_winsys_fence *base_fence = NULL;
bool do_flush = submission->flush_caches || submission->wait_dst_stage_mask;
bool can_patch = true;
uint32_t advance;
@ -4707,23 +4684,6 @@ radv_queue_submit_deferred(struct radv_deferred_queue_submission *submission,
struct radeon_cmdbuf *initial_flush_preamble_cs = NULL;
struct radeon_cmdbuf *continue_preamble_cs = NULL;
if (fence) {
/* Under most circumstances, out fences won't be temporary.
* However, the spec does allow it for opaque_fd.
*
* From the Vulkan 1.0.53 spec:
*
* "If the import is temporary, the implementation must
* restore the semaphore to its prior permanent state after
* submitting the next semaphore wait operation."
*/
struct radv_fence_part *part =
fence->temporary.kind != RADV_FENCE_NONE ?
&fence->temporary : &fence->permanent;
if (part->kind == RADV_FENCE_WINSYS)
base_fence = part->fence;
}
result = radv_get_preambles(queue, submission->cmd_buffers,
submission->cmd_buffer_count,
&initial_preamble_cs,
@ -4770,7 +4730,7 @@ radv_queue_submit_deferred(struct radv_deferred_queue_submission *submission,
&queue->device->empty_cs[queue->queue_family_index],
1, NULL, NULL,
&sem_info,
false, base_fence);
false);
if (result != VK_SUCCESS)
goto fail;
} else {
@ -4802,7 +4762,7 @@ radv_queue_submit_deferred(struct radv_deferred_queue_submission *submission,
result = queue->device->ws->cs_submit(ctx, queue->queue_idx, cs_array + j,
advance, initial_preamble, continue_preamble_cs,
&sem_info,
can_patch, base_fence);
can_patch);
if (result != VK_SUCCESS) {
free(cs_array);
goto fail;
@ -5028,7 +4988,7 @@ radv_queue_internal_submit(struct radv_queue *queue, struct radeon_cmdbuf *cs)
result = queue->device->ws->cs_submit(ctx, queue->queue_idx, &cs, 1,
NULL, NULL, &sem_info,
false, NULL);
false);
radv_free_sem_info(&sem_info);
if (result != VK_SUCCESS)
return false;
@ -5790,9 +5750,6 @@ radv_destroy_fence_part(struct radv_device *device,
switch (part->kind) {
case RADV_FENCE_NONE:
break;
case RADV_FENCE_WINSYS:
device->ws->destroy_fence(part->fence);
break;
case RADV_FENCE_SYNCOBJ:
device->ws->destroy_syncobj(device->ws, part->syncobj);
break;
@ -5822,11 +5779,9 @@ VkResult radv_CreateFence(
VkFence* pFence)
{
RADV_FROM_HANDLE(radv_device, device, _device);
const VkExportFenceCreateInfo *export =
vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO);
VkExternalFenceHandleTypeFlags handleTypes =
export ? export->handleTypes : 0;
bool create_signaled = false;
struct radv_fence *fence;
int ret;
fence = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*fence), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
@ -5835,29 +5790,16 @@ VkResult radv_CreateFence(
vk_object_base_init(&device->vk, &fence->base, VK_OBJECT_TYPE_FENCE);
if (device->always_use_syncobj || handleTypes) {
fence->permanent.kind = RADV_FENCE_SYNCOBJ;
fence->permanent.kind = RADV_FENCE_SYNCOBJ;
bool create_signaled = false;
if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
create_signaled = true;
if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
create_signaled = true;
int ret = device->ws->create_syncobj(device->ws, create_signaled,
&fence->permanent.syncobj);
if (ret) {
radv_destroy_fence(device, pAllocator, fence);
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
}
} else {
fence->permanent.kind = RADV_FENCE_WINSYS;
fence->permanent.fence = device->ws->create_fence();
if (!fence->permanent.fence) {
radv_destroy_fence(device, pAllocator, fence);
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
}
if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
device->ws->signal_fence(fence->permanent.fence);
ret = device->ws->create_syncobj(device->ws, create_signaled,
&fence->permanent.syncobj);
if (ret) {
radv_destroy_fence(device, pAllocator, fence);
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
}
*pFence = radv_fence_to_handle(fence);
@ -5880,22 +5822,6 @@ void radv_DestroyFence(
radv_destroy_fence(device, pAllocator, fence);
}
static bool radv_all_fences_plain_and_submitted(struct radv_device *device,
uint32_t fenceCount, const VkFence *pFences)
{
for (uint32_t i = 0; i < fenceCount; ++i) {
RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
struct radv_fence_part *part =
fence->temporary.kind != RADV_FENCE_NONE ?
&fence->temporary : &fence->permanent;
if (part->kind != RADV_FENCE_WINSYS ||
!device->ws->is_fence_waitable(part->fence))
return false;
}
return true;
}
static bool radv_all_fences_syncobj(uint32_t fenceCount, const VkFence *pFences)
{
for (uint32_t i = 0; i < fenceCount; ++i) {
@ -5924,8 +5850,7 @@ VkResult radv_WaitForFences(
timeout = radv_get_absolute_timeout(timeout);
if (device->always_use_syncobj &&
radv_all_fences_syncobj(fenceCount, pFences))
if (radv_all_fences_syncobj(fenceCount, pFences))
{
uint32_t *handles = malloc(sizeof(uint32_t) * fenceCount);
if (!handles)
@ -5949,36 +5874,6 @@ VkResult radv_WaitForFences(
}
if (!waitAll && fenceCount > 1) {
/* Not doing this by default for waitAll, due to needing to allocate twice. */
if (device->physical_device->rad_info.drm_minor >= 10 && radv_all_fences_plain_and_submitted(device, fenceCount, pFences)) {
uint32_t wait_count = 0;
struct radeon_winsys_fence **fences = malloc(sizeof(struct radeon_winsys_fence *) * fenceCount);
if (!fences)
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
for (uint32_t i = 0; i < fenceCount; ++i) {
RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
struct radv_fence_part *part =
fence->temporary.kind != RADV_FENCE_NONE ?
&fence->temporary : &fence->permanent;
assert(part->kind == RADV_FENCE_WINSYS);
if (device->ws->fence_wait(device->ws, part->fence, false, 0)) {
free(fences);
return VK_SUCCESS;
}
fences[wait_count++] = part->fence;
}
bool success = device->ws->fences_wait(device->ws, fences, wait_count,
waitAll, timeout - radv_get_current_time());
free(fences);
return success ? VK_SUCCESS : VK_TIMEOUT;
}
while(radv_get_current_time() <= timeout) {
for (uint32_t i = 0; i < fenceCount; ++i) {
if (radv_GetFenceStatus(_device, pFences[i]) == VK_SUCCESS)
@ -5990,7 +5885,6 @@ VkResult radv_WaitForFences(
for (uint32_t i = 0; i < fenceCount; ++i) {
RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
bool expired = false;
struct radv_fence_part *part =
fence->temporary.kind != RADV_FENCE_NONE ?
@ -5999,19 +5893,6 @@ VkResult radv_WaitForFences(
switch (part->kind) {
case RADV_FENCE_NONE:
break;
case RADV_FENCE_WINSYS:
if (!device->ws->is_fence_waitable(part->fence)) {
while (!device->ws->is_fence_waitable(part->fence) &&
radv_get_current_time() <= timeout)
/* Do nothing */;
}
expired = device->ws->fence_wait(device->ws,
part->fence,
true, timeout);
if (!expired)
return VK_TIMEOUT;
break;
case RADV_FENCE_SYNCOBJ:
if (!device->ws->wait_syncobj(device->ws,
&part->syncobj, 1, true,
@ -6049,9 +5930,6 @@ VkResult radv_ResetFences(VkDevice _device,
struct radv_fence_part *part = &fence->permanent;
switch (part->kind) {
case RADV_FENCE_WINSYS:
device->ws->reset_fence(part->fence);
break;
case RADV_FENCE_SYNCOBJ:
device->ws->reset_syncobj(device->ws, part->syncobj);
break;
@ -6078,10 +5956,6 @@ VkResult radv_GetFenceStatus(VkDevice _device, VkFence _fence)
switch (part->kind) {
case RADV_FENCE_NONE:
break;
case RADV_FENCE_WINSYS:
if (!device->ws->fence_wait(device->ws, part->fence, false, 0))
return VK_NOT_READY;
break;
case RADV_FENCE_SYNCOBJ: {
bool success = device->ws->wait_syncobj(device->ws,
&part->syncobj, 1, true, 0);
@ -6270,9 +6144,6 @@ void radv_destroy_semaphore_part(struct radv_device *device,
switch(part->kind) {
case RADV_SEMAPHORE_NONE:
break;
case RADV_SEMAPHORE_WINSYS:
device->ws->destroy_sem(part->ws_sem);
break;
case RADV_SEMAPHORE_TIMELINE:
radv_destroy_timeline(device, &part->timeline);
break;
@ -6316,10 +6187,6 @@ VkResult radv_CreateSemaphore(
VkSemaphore* pSemaphore)
{
RADV_FROM_HANDLE(radv_device, device, _device);
const VkExportSemaphoreCreateInfo *export =
vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO);
VkExternalSemaphoreHandleTypeFlags handleTypes =
export ? export->handleTypes : 0;
uint64_t initial_value = 0;
VkSemaphoreTypeKHR type = radv_get_semaphore_type(pCreateInfo->pNext, &initial_value);
@ -6348,8 +6215,7 @@ VkResult radv_CreateSemaphore(
} else if (type == VK_SEMAPHORE_TYPE_TIMELINE) {
radv_create_timeline(&sem->permanent.timeline, initial_value);
sem->permanent.kind = RADV_SEMAPHORE_TIMELINE;
} else if (device->always_use_syncobj || handleTypes) {
assert (device->physical_device->rad_info.has_syncobj);
} else {
int ret = device->ws->create_syncobj(device->ws, false,
&sem->permanent.syncobj);
if (ret) {
@ -6357,13 +6223,6 @@ VkResult radv_CreateSemaphore(
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
}
sem->permanent.kind = RADV_SEMAPHORE_SYNCOBJ;
} else {
sem->permanent.ws_sem = device->ws->create_sem(device->ws);
if (!sem->permanent.ws_sem) {
radv_destroy_semaphore(device, pAllocator, sem);
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
}
sem->permanent.kind = RADV_SEMAPHORE_WINSYS;
}
*pSemaphore = radv_semaphore_to_handle(sem);
@ -6410,7 +6269,6 @@ radv_GetSemaphoreCounterValue(VkDevice _device,
}
case RADV_SEMAPHORE_NONE:
case RADV_SEMAPHORE_SYNCOBJ:
case RADV_SEMAPHORE_WINSYS:
unreachable("Invalid semaphore type");
}
unreachable("Unhandled semaphore type");
@ -6520,7 +6378,6 @@ radv_SignalSemaphore(VkDevice _device,
}
case RADV_SEMAPHORE_NONE:
case RADV_SEMAPHORE_SYNCOBJ:
case RADV_SEMAPHORE_WINSYS:
unreachable("Invalid semaphore type");
}
return VK_SUCCESS;
@ -7922,11 +7779,8 @@ void radv_GetPhysicalDeviceExternalSemaphoreProperties(
pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
pExternalSemaphoreProperties->compatibleHandleTypes = 0;
pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
/* Require has_syncobj_wait_for_submit for the syncobj signal ioctl introduced at virtually the same time */
} else if (pdevice->rad_info.has_syncobj_wait_for_submit &&
(pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT ||
pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
} else if (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT ||
pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) {
pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
@ -8020,11 +7874,8 @@ void radv_GetPhysicalDeviceExternalFenceProperties(
const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
VkExternalFenceProperties *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 ||
pExternalFenceInfo->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)) {
if (pExternalFenceInfo->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT ||
pExternalFenceInfo->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT) {
pExternalFenceProperties->exportFromImportedHandleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
pExternalFenceProperties->compatibleHandleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
pExternalFenceProperties->externalFenceFeatures = VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT |

View File

@ -741,7 +741,6 @@ struct radv_device {
int queue_count[RADV_MAX_QUEUE_FAMILIES];
struct radeon_cmdbuf *empty_cs[RADV_MAX_QUEUE_FAMILIES];
bool always_use_syncobj;
bool pbb_allowed;
bool dfsm_allowed;
uint32_t tess_offchip_block_dw_size;
@ -2405,7 +2404,6 @@ struct radv_query_pool {
typedef enum {
RADV_SEMAPHORE_NONE,
RADV_SEMAPHORE_WINSYS,
RADV_SEMAPHORE_SYNCOBJ,
RADV_SEMAPHORE_TIMELINE_SYNCOBJ,
RADV_SEMAPHORE_TIMELINE,
@ -2458,7 +2456,6 @@ struct radv_semaphore_part {
radv_semaphore_kind kind;
union {
uint32_t syncobj;
struct radeon_winsys_sem *ws_sem;
struct radv_timeline timeline;
struct radv_timeline_syncobj timeline_syncobj;
};
@ -2511,20 +2508,14 @@ void radv_initialize_fmask(struct radv_cmd_buffer *cmd_buffer,
typedef enum {
RADV_FENCE_NONE,
RADV_FENCE_WINSYS,
RADV_FENCE_SYNCOBJ,
} radv_fence_kind;
struct radv_fence_part {
radv_fence_kind kind;
union {
/* AMDGPU winsys fence. */
struct radeon_winsys_fence *fence;
/* DRM syncobj handle for syncobj-based fences. */
uint32_t syncobj;
};
/* DRM syncobj handle for syncobj-based fences. */
uint32_t syncobj;
};
struct radv_fence {
@ -2624,8 +2615,6 @@ void radv_describe_barrier_end_delayed(struct radv_cmd_buffer *cmd_buffer);
void radv_describe_layout_transition(struct radv_cmd_buffer *cmd_buffer,
const struct radv_barrier_data *barrier);
struct radeon_winsys_sem;
uint64_t radv_get_current_time(void);
static inline uint32_t

View File

@ -157,7 +157,6 @@ struct radeon_bo_metadata {
uint32_t metadata[64];
};
struct radeon_winsys_fence;
struct radeon_winsys_ctx;
struct radeon_winsys_bo {
@ -171,10 +170,8 @@ struct radv_winsys_sem_counts {
uint32_t syncobj_count;
uint32_t syncobj_reset_count; /* for wait only, whether to reset the syncobj */
uint32_t timeline_syncobj_count;
uint32_t sem_count;
uint32_t *syncobj;
uint64_t *points;
struct radeon_winsys_sem **sem;
};
struct radv_winsys_sem_info {
@ -298,8 +295,7 @@ struct radeon_winsys {
struct radeon_cmdbuf *initial_preamble_cs,
struct radeon_cmdbuf *continue_preamble_cs,
struct radv_winsys_sem_info *sem_info,
bool can_patch,
struct radeon_winsys_fence *fence);
bool can_patch);
void (*cs_add_buffer)(struct radeon_cmdbuf *cs,
struct radeon_winsys_bo *bo);
@ -317,26 +313,6 @@ struct radeon_winsys {
const struct ac_surf_info *surf_info,
struct radeon_surf *surf);
struct radeon_winsys_fence *(*create_fence)();
void (*destroy_fence)(struct radeon_winsys_fence *fence);
void (*reset_fence)(struct radeon_winsys_fence *fence);
void (*signal_fence)(struct radeon_winsys_fence *fence);
bool (*is_fence_waitable)(struct radeon_winsys_fence *fence);
bool (*fence_wait)(struct radeon_winsys *ws,
struct radeon_winsys_fence *fence,
bool absolute,
uint64_t timeout);
bool (*fences_wait)(struct radeon_winsys *ws,
struct radeon_winsys_fence *const *fences,
uint32_t fence_count,
bool wait_all,
uint64_t timeout);
/* old semaphores - non shareable */
struct radeon_winsys_sem *(*create_sem)(struct radeon_winsys *ws);
void (*destroy_sem)(struct radeon_winsys_sem *sem);
/* new shareable sync objects */
int (*create_syncobj)(struct radeon_winsys *ws, bool create_signaled,
uint32_t *handle);
void (*destroy_syncobj)(struct radeon_winsys *ws, uint32_t handle);

View File

@ -268,9 +268,6 @@ VkResult radv_AcquireNextImage2KHR(
switch (part->kind) {
case RADV_FENCE_NONE:
break;
case RADV_FENCE_WINSYS:
device->ws->signal_fence(part->fence);
break;
case RADV_FENCE_SYNCOBJ:
device->ws->signal_syncobj(device->ws, part->syncobj, 0);
break;
@ -285,7 +282,6 @@ VkResult radv_AcquireNextImage2KHR(
switch (part->kind) {
case RADV_SEMAPHORE_NONE:
case RADV_SEMAPHORE_WINSYS:
/* Do not need to do anything. */
break;
case RADV_SEMAPHORE_TIMELINE:

View File

@ -500,10 +500,9 @@ radv_amdgpu_winsys_bo_create(struct radeon_winsys *_ws,
}
if (flags & RADEON_FLAG_GTT_WC)
request.flags |= AMDGPU_GEM_CREATE_CPU_GTT_USWC;
if (!(flags & RADEON_FLAG_IMPLICIT_SYNC) && ws->info.drm_minor >= 22)
if (!(flags & RADEON_FLAG_IMPLICIT_SYNC))
request.flags |= AMDGPU_GEM_CREATE_EXPLICIT_SYNC;
if (flags & RADEON_FLAG_NO_INTERPROCESS_SHARING &&
ws->info.has_local_buffers &&
(ws->use_local_bos || (flags & RADEON_FLAG_PREFER_LOCAL_BO))) {
bo->base.is_local = true;
request.flags |= AMDGPU_GEM_CREATE_VM_ALWAYS_VALID;

View File

@ -127,10 +127,6 @@ struct radv_amdgpu_cs_request {
};
static int radv_amdgpu_signal_sems(struct radv_amdgpu_ctx *ctx,
uint32_t ip_type,
uint32_t ring,
struct radv_winsys_sem_info *sem_info);
static int radv_amdgpu_cs_submit(struct radv_amdgpu_ctx *ctx,
struct radv_amdgpu_cs_request *request,
struct radv_winsys_sem_info *sem_info);
@ -147,114 +143,6 @@ static void radv_amdgpu_request_to_fence(struct radv_amdgpu_ctx *ctx,
fence->user_ptr = (volatile uint64_t*)(ctx->fence_map + req->ip_type * MAX_RINGS_PER_TYPE + req->ring);
}
static struct radeon_winsys_fence *radv_amdgpu_create_fence()
{
struct radv_amdgpu_fence *fence = calloc(1, sizeof(struct radv_amdgpu_fence));
if (!fence)
return NULL;
fence->fence.fence = UINT64_MAX;
return (struct radeon_winsys_fence*)fence;
}
static void radv_amdgpu_destroy_fence(struct radeon_winsys_fence *_fence)
{
struct radv_amdgpu_fence *fence = (struct radv_amdgpu_fence *)_fence;
free(fence);
}
static void radv_amdgpu_reset_fence(struct radeon_winsys_fence *_fence)
{
struct radv_amdgpu_fence *fence = (struct radv_amdgpu_fence *)_fence;
fence->fence.fence = UINT64_MAX;
}
static void radv_amdgpu_signal_fence(struct radeon_winsys_fence *_fence)
{
struct radv_amdgpu_fence *fence = (struct radv_amdgpu_fence *)_fence;
fence->fence.fence = 0;
}
static bool radv_amdgpu_is_fence_waitable(struct radeon_winsys_fence *_fence)
{
struct radv_amdgpu_fence *fence = (struct radv_amdgpu_fence *)_fence;
return fence->fence.fence < UINT64_MAX;
}
static bool radv_amdgpu_fence_wait(struct radeon_winsys *_ws,
struct radeon_winsys_fence *_fence,
bool absolute,
uint64_t timeout)
{
struct radv_amdgpu_fence *fence = (struct radv_amdgpu_fence *)_fence;
unsigned flags = absolute ? AMDGPU_QUERY_FENCE_TIMEOUT_IS_ABSOLUTE : 0;
int r;
uint32_t expired = 0;
/* Special casing 0 and UINT64_MAX so that they work without user_ptr/fence.ctx */
if (fence->fence.fence == UINT64_MAX)
return false;
if (fence->fence.fence == 0)
return true;
if (fence->user_ptr) {
if (*fence->user_ptr >= fence->fence.fence)
return true;
if (!absolute && !timeout)
return false;
}
/* Now use the libdrm query. */
r = amdgpu_cs_query_fence_status(&fence->fence,
timeout,
flags,
&expired);
if (r) {
fprintf(stderr, "amdgpu: radv_amdgpu_cs_query_fence_status failed.\n");
return false;
}
if (expired)
return true;
return false;
}
static bool radv_amdgpu_fences_wait(struct radeon_winsys *_ws,
struct radeon_winsys_fence *const *_fences,
uint32_t fence_count,
bool wait_all,
uint64_t timeout)
{
struct amdgpu_cs_fence *fences = malloc(sizeof(struct amdgpu_cs_fence) * fence_count);
int r;
uint32_t expired = 0, first = 0;
if (!fences)
return false;
for (uint32_t i = 0; i < fence_count; ++i)
fences[i] = ((struct radv_amdgpu_fence *)_fences[i])->fence;
/* Now use the libdrm query. */
r = amdgpu_cs_wait_fences(fences, fence_count, wait_all,
timeout, &expired, &first);
free(fences);
if (r) {
fprintf(stderr, "amdgpu: amdgpu_cs_wait_fences failed.\n");
return false;
}
if (expired)
return true;
return false;
}
static void radv_amdgpu_cs_destroy(struct radeon_cmdbuf *rcs)
{
struct radv_amdgpu_cs *cs = radv_amdgpu_cs(rcs);
@ -840,11 +728,9 @@ radv_amdgpu_winsys_cs_submit_chained(struct radeon_winsys_ctx *_ctx,
struct radv_winsys_sem_info *sem_info,
struct radeon_cmdbuf **cs_array,
unsigned cs_count,
struct radeon_cmdbuf *initial_preamble_cs,
struct radeon_winsys_fence *_fence)
struct radeon_cmdbuf *initial_preamble_cs)
{
struct radv_amdgpu_ctx *ctx = radv_amdgpu_ctx(_ctx);
struct radv_amdgpu_fence *fence = (struct radv_amdgpu_fence *)_fence;
struct radv_amdgpu_cs *cs0 = radv_amdgpu_cs(cs_array[0]);
struct radv_amdgpu_winsys *aws = cs0->ws;
struct drm_amdgpu_bo_list_entry *handles = NULL;
@ -910,9 +796,6 @@ radv_amdgpu_winsys_cs_submit_chained(struct radeon_winsys_ctx *_ctx,
if (result != VK_SUCCESS)
goto fail;
if (fence)
radv_amdgpu_request_to_fence(ctx, fence, &request);
radv_assign_last_submit(ctx, &request);
fail:
@ -926,11 +809,9 @@ radv_amdgpu_winsys_cs_submit_fallback(struct radeon_winsys_ctx *_ctx,
struct radv_winsys_sem_info *sem_info,
struct radeon_cmdbuf **cs_array,
unsigned cs_count,
struct radeon_cmdbuf *initial_preamble_cs,
struct radeon_winsys_fence *_fence)
struct radeon_cmdbuf *initial_preamble_cs)
{
struct radv_amdgpu_ctx *ctx = radv_amdgpu_ctx(_ctx);
struct radv_amdgpu_fence *fence = (struct radv_amdgpu_fence *)_fence;
struct drm_amdgpu_bo_list_entry *handles = NULL;
struct radv_amdgpu_cs_request request;
struct amdgpu_cs_ib_info *ibs;
@ -996,9 +877,6 @@ radv_amdgpu_winsys_cs_submit_fallback(struct radeon_winsys_ctx *_ctx,
if (result != VK_SUCCESS)
goto fail;
if (fence)
radv_amdgpu_request_to_fence(ctx, fence, &request);
radv_assign_last_submit(ctx, &request);
fail:
@ -1013,11 +891,9 @@ radv_amdgpu_winsys_cs_submit_sysmem(struct radeon_winsys_ctx *_ctx,
struct radeon_cmdbuf **cs_array,
unsigned cs_count,
struct radeon_cmdbuf *initial_preamble_cs,
struct radeon_cmdbuf *continue_preamble_cs,
struct radeon_winsys_fence *_fence)
struct radeon_cmdbuf *continue_preamble_cs)
{
struct radv_amdgpu_ctx *ctx = radv_amdgpu_ctx(_ctx);
struct radv_amdgpu_fence *fence = (struct radv_amdgpu_fence *)_fence;
struct radv_amdgpu_cs *cs0 = radv_amdgpu_cs(cs_array[0]);
struct radeon_winsys *ws = (struct radeon_winsys*)cs0->ws;
struct radv_amdgpu_winsys *aws = cs0->ws;
@ -1198,8 +1074,6 @@ radv_amdgpu_winsys_cs_submit_sysmem(struct radeon_winsys_ctx *_ctx,
i += cnt;
}
if (fence)
radv_amdgpu_request_to_fence(ctx, fence, &request);
radv_assign_last_submit(ctx, &request);
@ -1213,26 +1087,23 @@ static VkResult radv_amdgpu_winsys_cs_submit(struct radeon_winsys_ctx *_ctx,
struct radeon_cmdbuf *initial_preamble_cs,
struct radeon_cmdbuf *continue_preamble_cs,
struct radv_winsys_sem_info *sem_info,
bool can_patch,
struct radeon_winsys_fence *_fence)
bool can_patch)
{
struct radv_amdgpu_cs *cs = radv_amdgpu_cs(cs_array[0]);
struct radv_amdgpu_ctx *ctx = radv_amdgpu_ctx(_ctx);
VkResult result;
assert(sem_info);
if (!cs->ws->use_ib_bos) {
result = radv_amdgpu_winsys_cs_submit_sysmem(_ctx, queue_idx, sem_info, cs_array,
cs_count, initial_preamble_cs, continue_preamble_cs, _fence);
cs_count, initial_preamble_cs, continue_preamble_cs);
} else if (can_patch) {
result = radv_amdgpu_winsys_cs_submit_chained(_ctx, queue_idx, sem_info, cs_array,
cs_count, initial_preamble_cs, _fence);
cs_count, initial_preamble_cs);
} else {
result = radv_amdgpu_winsys_cs_submit_fallback(_ctx, queue_idx, sem_info, cs_array,
cs_count, initial_preamble_cs, _fence);
cs_count, initial_preamble_cs);
}
radv_amdgpu_signal_sems(ctx, cs->hw_ip, queue_idx, sem_info);
return result;
}
@ -1382,37 +1253,6 @@ static bool radv_amdgpu_ctx_wait_idle(struct radeon_winsys_ctx *rwctx,
return true;
}
static struct radeon_winsys_sem *radv_amdgpu_create_sem(struct radeon_winsys *_ws)
{
struct amdgpu_cs_fence *sem = CALLOC_STRUCT(amdgpu_cs_fence);
if (!sem)
return NULL;
return (struct radeon_winsys_sem *)sem;
}
static void radv_amdgpu_destroy_sem(struct radeon_winsys_sem *_sem)
{
struct amdgpu_cs_fence *sem = (struct amdgpu_cs_fence *)_sem;
FREE(sem);
}
static int radv_amdgpu_signal_sems(struct radv_amdgpu_ctx *ctx,
uint32_t ip_type,
uint32_t ring,
struct radv_winsys_sem_info *sem_info)
{
for (unsigned i = 0; i < sem_info->signal.sem_count; i++) {
struct amdgpu_cs_fence *sem = (struct amdgpu_cs_fence *)(sem_info->signal.sem)[i];
if (sem->context)
return -EINVAL;
*sem = ctx->last_submission[ip_type][ring].fence;
}
return 0;
}
static void *radv_amdgpu_cs_alloc_syncobj_chunk(struct radv_winsys_sem_counts *counts,
const uint32_t *syncobj_override,
struct drm_amdgpu_cs_chunk *chunk, int chunk_id)
@ -1570,17 +1410,14 @@ radv_amdgpu_cs_submit(struct radv_amdgpu_ctx *ctx,
int size;
struct drm_amdgpu_cs_chunk *chunks;
struct drm_amdgpu_cs_chunk_data *chunk_data;
struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL;
bool use_bo_list_create = ctx->ws->info.drm_minor < 27;
struct drm_amdgpu_bo_list_in bo_list_in;
void *wait_syncobj = NULL, *signal_syncobj = NULL;
uint32_t *in_syncobjs = NULL;
int i;
struct amdgpu_cs_fence *sem;
uint32_t bo_list = 0;
VkResult result = VK_SUCCESS;
size = request->number_of_ibs + 2 /* user fence */ + (!use_bo_list_create ? 1 : 0) + 3;
size = request->number_of_ibs + 2 /* user fence */ + 4;
chunks = malloc(sizeof(chunks[0]) * size);
if (!chunks)
@ -1644,37 +1481,6 @@ radv_amdgpu_cs_submit(struct radv_amdgpu_ctx *ctx,
}
num_chunks++;
if (sem_info->wait.sem_count == 0)
sem_info->cs_emit_wait = false;
}
if (sem_info->wait.sem_count && sem_info->cs_emit_wait) {
sem_dependencies = malloc(sizeof(sem_dependencies[0]) * sem_info->wait.sem_count);
if (!sem_dependencies) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto error_out;
}
int sem_count = 0;
for (unsigned j = 0; j < sem_info->wait.sem_count; j++) {
sem = (struct amdgpu_cs_fence *)sem_info->wait.sem[j];
if (!sem->context)
continue;
struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++];
amdgpu_cs_chunk_fence_to_dep(sem, dep);
sem->context = NULL;
}
i = num_chunks++;
/* dependencies chunk */
chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES;
chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 * sem_count;
chunks[i].chunk_data = (uint64_t)(uintptr_t)sem_dependencies;
sem_info->cs_emit_wait = false;
}
@ -1697,35 +1503,17 @@ radv_amdgpu_cs_submit(struct radv_amdgpu_ctx *ctx,
num_chunks++;
}
if (use_bo_list_create) {
/* Legacy path creating the buffer list handle and passing it
* to the CS ioctl.
*/
r = amdgpu_bo_list_create_raw(ctx->ws->dev, request->num_handles,
request->handles, &bo_list);
if (r) {
if (r == -ENOMEM) {
fprintf(stderr, "amdgpu: Not enough memory for buffer list creation.\n");
result = VK_ERROR_OUT_OF_HOST_MEMORY;
} else {
fprintf(stderr, "amdgpu: buffer list creation failed (%d).\n", r);
result = VK_ERROR_UNKNOWN;
}
goto error_out;
}
} else {
/* Standard path passing the buffer list via the CS ioctl. */
bo_list_in.operation = ~0;
bo_list_in.list_handle = ~0;
bo_list_in.bo_number = request->num_handles;
bo_list_in.bo_info_size = sizeof(struct drm_amdgpu_bo_list_entry);
bo_list_in.bo_info_ptr = (uint64_t)(uintptr_t)request->handles;
/* Standard path passing the buffer list via the CS ioctl. */
bo_list_in.operation = ~0;
bo_list_in.list_handle = ~0;
bo_list_in.bo_number = request->num_handles;
bo_list_in.bo_info_size = sizeof(struct drm_amdgpu_bo_list_entry);
bo_list_in.bo_info_ptr = (uint64_t)(uintptr_t)request->handles;
chunks[num_chunks].chunk_id = AMDGPU_CHUNK_ID_BO_HANDLES;
chunks[num_chunks].length_dw = sizeof(struct drm_amdgpu_bo_list_in) / 4;
chunks[num_chunks].chunk_data = (uintptr_t)&bo_list_in;
num_chunks++;
}
chunks[num_chunks].chunk_id = AMDGPU_CHUNK_ID_BO_HANDLES;
chunks[num_chunks].length_dw = sizeof(struct drm_amdgpu_bo_list_in) / 4;
chunks[num_chunks].chunk_data = (uintptr_t)&bo_list_in;
num_chunks++;
r = amdgpu_cs_submit_raw2(ctx->ws->dev,
ctx->ctx,
@ -1758,7 +1546,6 @@ error_out:
}
free(chunks);
free(chunk_data);
free(sem_dependencies);
free(wait_syncobj);
free(signal_syncobj);
return result;
@ -1918,13 +1705,6 @@ void radv_amdgpu_cs_init_functions(struct radv_amdgpu_winsys *ws)
ws->base.cs_execute_secondary = radv_amdgpu_cs_execute_secondary;
ws->base.cs_submit = radv_amdgpu_winsys_cs_submit;
ws->base.cs_dump = radv_amdgpu_winsys_cs_dump;
ws->base.create_fence = radv_amdgpu_create_fence;
ws->base.destroy_fence = radv_amdgpu_destroy_fence;
ws->base.reset_fence = radv_amdgpu_reset_fence;
ws->base.signal_fence = radv_amdgpu_signal_fence;
ws->base.is_fence_waitable = radv_amdgpu_is_fence_waitable;
ws->base.create_sem = radv_amdgpu_create_sem;
ws->base.destroy_sem = radv_amdgpu_destroy_sem;
ws->base.create_syncobj = radv_amdgpu_create_syncobj;
ws->base.destroy_syncobj = radv_amdgpu_destroy_syncobj;
ws->base.reset_syncobj = radv_amdgpu_reset_syncobj;
@ -1936,6 +1716,4 @@ void radv_amdgpu_cs_init_functions(struct radv_amdgpu_winsys *ws)
ws->base.import_syncobj = radv_amdgpu_import_syncobj;
ws->base.export_syncobj_to_sync_file = radv_amdgpu_export_syncobj_to_sync_file;
ws->base.import_syncobj_from_sync_file = radv_amdgpu_import_syncobj_from_sync_file;
ws->base.fence_wait = radv_amdgpu_fence_wait;
ws->base.fences_wait = radv_amdgpu_fences_wait;
}

View File

@ -45,6 +45,11 @@ do_winsys_init(struct radv_amdgpu_winsys *ws, int fd)
if (!ac_query_gpu_info(fd, ws->dev, &ws->info, &ws->amdinfo))
return false;
if (ws->info.drm_minor < 35) {
fprintf(stderr, "radv: DRM 3.35+ is required (Linux kernel 4.15+)\n");
return false;
}
/* LLVM 11 is required for GFX10.3. */
if (ws->info.chip_class == GFX10_3 && ws->use_llvm && LLVM_VERSION_MAJOR < 11) {
fprintf(stderr, "radv: GFX 10.3 requires LLVM 11 or higher\n");

View File

@ -106,7 +106,6 @@ static void radv_null_winsys_query_info(struct radeon_winsys *rws,
}
info->pci_id = gpu_info[info->family].pci_id;
info->has_syncobj_wait_for_submit = true;
info->max_se = 4;
info->num_se = 4;
if (info->chip_class >= GFX10_3)