X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Famd%2Fvulkan%2Fradv_device.c;h=4d43f25aee029ab0a7e3af8b1eb2b4b3329efb4b;hb=e67fc11c26111ae7aa8d140a5f62074b5e0b43c3;hp=51b44cc22275de9d891055da9171f0c3d6e1661c;hpb=f9eb1ef870eba9fdacf9a8cbd815ec3bff81db05;p=mesa.git diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 51b44cc2227..4d43f25aee0 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -43,24 +43,32 @@ #include "ac_llvm_util.h" #include "vk_format.h" #include "sid.h" -#include "gfx9d.h" -#include "addrlib/gfx9/chip/gfx9_enum.h" +#include "git_sha1.h" +#include "util/build_id.h" #include "util/debug.h" +#include "util/mesa-sha1.h" +#include "compiler/glsl_types.h" +#include "util/xmlpool.h" static int radv_device_get_cache_uuid(enum radeon_family family, void *uuid) { - uint32_t mesa_timestamp, llvm_timestamp; - uint16_t f = family; + struct mesa_sha1 ctx; + unsigned char sha1[20]; + unsigned ptr_size = sizeof(void*); + memset(uuid, 0, VK_UUID_SIZE); - if (!disk_cache_get_function_timestamp(radv_device_get_cache_uuid, &mesa_timestamp) || - !disk_cache_get_function_timestamp(LLVMInitializeAMDGPUTargetInfo, &llvm_timestamp)) + _mesa_sha1_init(&ctx); + + if (!disk_cache_get_function_identifier(radv_device_get_cache_uuid, &ctx) || + !disk_cache_get_function_identifier(LLVMInitializeAMDGPUTargetInfo, &ctx)) return -1; - memcpy(uuid, &mesa_timestamp, 4); - memcpy((char*)uuid + 4, &llvm_timestamp, 4); - memcpy((char*)uuid + 8, &f, 2); - snprintf((char*)uuid + 10, VK_UUID_SIZE - 10, "radv"); + _mesa_sha1_update(&ctx, &family, sizeof(family)); + _mesa_sha1_update(&ctx, &ptr_size, sizeof(ptr_size)); + _mesa_sha1_final(&ctx, sha1); + + memcpy(uuid, sha1, VK_UUID_SIZE); return 0; } @@ -80,7 +88,6 @@ static void radv_get_device_name(enum radeon_family family, char *name, size_t name_len) { const char *chip_string; - char llvm_string[32] = {}; switch (family) { case CHIP_TAHITI: chip_string = "AMD RADV TAHITI"; break; @@ -92,7 +99,6 @@ radv_get_device_name(enum radeon_family family, char *name, size_t name_len) case CHIP_KAVERI: chip_string = "AMD RADV KAVERI"; break; case CHIP_KABINI: chip_string = "AMD RADV KABINI"; break; case CHIP_HAWAII: chip_string = "AMD RADV HAWAII"; break; - case CHIP_MULLINS: chip_string = "AMD RADV MULLINS"; break; case CHIP_TONGA: chip_string = "AMD RADV TONGA"; break; case CHIP_ICELAND: chip_string = "AMD RADV ICELAND"; break; case CHIP_CARRIZO: chip_string = "AMD RADV CARRIZO"; break; @@ -104,29 +110,39 @@ radv_get_device_name(enum radeon_family family, char *name, size_t name_len) case CHIP_VEGAM: chip_string = "AMD RADV VEGA M"; break; case CHIP_VEGA10: chip_string = "AMD RADV VEGA10"; break; case CHIP_VEGA12: chip_string = "AMD RADV VEGA12"; break; + case CHIP_VEGA20: chip_string = "AMD RADV VEGA20"; break; case CHIP_RAVEN: chip_string = "AMD RADV RAVEN"; break; + case CHIP_RAVEN2: chip_string = "AMD RADV RAVEN2"; break; default: chip_string = "AMD RADV unknown"; break; } - snprintf(llvm_string, sizeof(llvm_string), - " (LLVM %i.%i.%i)", (HAVE_LLVM >> 8) & 0xff, - HAVE_LLVM & 0xff, MESA_LLVM_VERSION_PATCH); - snprintf(name, name_len, "%s%s", chip_string, llvm_string); + snprintf(name, name_len, "%s (LLVM " MESA_LLVM_VERSION_STRING ")", chip_string); +} + +static uint64_t +radv_get_visible_vram_size(struct radv_physical_device *device) +{ + return MIN2(device->rad_info.vram_size, device->rad_info.vram_vis_size); +} + +static uint64_t +radv_get_vram_size(struct radv_physical_device *device) +{ + return device->rad_info.vram_size - radv_get_visible_vram_size(device); } static void radv_physical_device_init_mem_types(struct radv_physical_device *device) { STATIC_ASSERT(RADV_MEM_HEAP_COUNT <= VK_MAX_MEMORY_HEAPS); - uint64_t visible_vram_size = MIN2(device->rad_info.vram_size, - device->rad_info.vram_vis_size); - + uint64_t visible_vram_size = radv_get_visible_vram_size(device); + uint64_t vram_size = radv_get_vram_size(device); int vram_index = -1, visible_vram_index = -1, gart_index = -1; device->memory_properties.memoryHeapCount = 0; - if (device->rad_info.vram_size - visible_vram_size > 0) { + if (vram_size > 0) { vram_index = device->memory_properties.memoryHeapCount++; device->memory_properties.memoryHeaps[vram_index] = (VkMemoryHeap) { - .size = device->rad_info.vram_size - visible_vram_size, + .size = vram_size, .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, }; } @@ -202,11 +218,11 @@ radv_handle_env_var_force_family(struct radv_physical_device *device) if (i >= CHIP_VEGA10) device->rad_info.chip_class = GFX9; else if (i >= CHIP_TONGA) - device->rad_info.chip_class = VI; + device->rad_info.chip_class = GFX8; else if (i >= CHIP_BONAIRE) - device->rad_info.chip_class = CIK; + device->rad_info.chip_class = GFX7; else - device->rad_info.chip_class = SI; + device->rad_info.chip_class = GFX6; return; } @@ -225,37 +241,69 @@ radv_physical_device_init(struct radv_physical_device *device, VkResult result; drmVersionPtr version; int fd; + int master_fd = -1; fd = open(path, O_RDWR | O_CLOEXEC); - if (fd < 0) - return vk_error(VK_ERROR_INCOMPATIBLE_DRIVER); + if (fd < 0) { + if (instance->debug_flags & RADV_DEBUG_STARTUP) + radv_logi("Could not open device '%s'", path); + + return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER); + } version = drmGetVersion(fd); if (!version) { close(fd); - return vk_errorf(VK_ERROR_INCOMPATIBLE_DRIVER, + + if (instance->debug_flags & RADV_DEBUG_STARTUP) + radv_logi("Could not get the kernel driver version for device '%s'", path); + + return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER, "failed to get version %s: %m", path); } if (strcmp(version->name, "amdgpu")) { drmFreeVersion(version); close(fd); + + if (instance->debug_flags & RADV_DEBUG_STARTUP) + radv_logi("Device '%s' is not using the amdgpu kernel driver.", path); + return VK_ERROR_INCOMPATIBLE_DRIVER; } drmFreeVersion(version); + if (instance->debug_flags & RADV_DEBUG_STARTUP) + radv_logi("Found compatible device '%s'.", path); + device->_loader_data.loaderMagic = ICD_LOADER_MAGIC; device->instance = instance; - assert(strlen(path) < ARRAY_SIZE(device->path)); - strncpy(device->path, path, ARRAY_SIZE(device->path)); device->ws = radv_amdgpu_winsys_create(fd, instance->debug_flags, instance->perftest_flags); if (!device->ws) { - result = VK_ERROR_INCOMPATIBLE_DRIVER; + result = vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER); goto fail; } + if (instance->enabled_extensions.KHR_display) { + master_fd = open(drm_device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC); + if (master_fd >= 0) { + uint32_t accel_working = 0; + struct drm_amdgpu_info request = { + .return_pointer = (uintptr_t)&accel_working, + .return_size = sizeof(accel_working), + .query = AMDGPU_INFO_ACCEL_WORKING + }; + + if (drmCommandWrite(master_fd, DRM_AMDGPU_INFO, &request, sizeof (struct drm_amdgpu_info)) < 0 || !accel_working) { + close(master_fd); + master_fd = -1; + } + } + } + + device->master_fd = master_fd; device->local_fd = fd; device->ws->query_info(device->ws, &device->rad_info); @@ -265,7 +313,7 @@ radv_physical_device_init(struct radv_physical_device *device, if (radv_device_get_cache_uuid(device->rad_info.family, device->cache_uuid)) { device->ws->destroy(device->ws); - result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED, + result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED, "cannot generate UUID"); goto fail; } @@ -282,11 +330,11 @@ radv_physical_device_init(struct radv_physical_device *device, disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE * 2); device->disk_cache = disk_cache_create(device->name, buf, shader_env_flags); - if (device->rad_info.chip_class < VI || + if (device->rad_info.chip_class < GFX8 || device->rad_info.chip_class > GFX9) fprintf(stderr, "WARNING: radv is not a conformant vulkan implementation, testing use only.\n"); - radv_get_driver_uuid(&device->device_uuid); + radv_get_driver_uuid(&device->driver_uuid); radv_get_device_uuid(&device->rad_info, &device->device_uuid); if (device->rad_info.family == CHIP_STONEY || @@ -294,45 +342,62 @@ radv_physical_device_init(struct radv_physical_device *device, device->has_rbplus = true; device->rbplus_allowed = device->rad_info.family == CHIP_STONEY || device->rad_info.family == CHIP_VEGA12 || - device->rad_info.family == CHIP_RAVEN; + device->rad_info.family == CHIP_RAVEN || + device->rad_info.family == CHIP_RAVEN2; } /* The mere presence of CLEAR_STATE in the IB causes random GPU hangs - * on SI. + * on GFX6. */ - device->has_clear_state = device->rad_info.chip_class >= CIK; + device->has_clear_state = device->rad_info.chip_class >= GFX7; - device->cpdma_prefetch_writes_memory = device->rad_info.chip_class <= VI; + device->cpdma_prefetch_writes_memory = device->rad_info.chip_class <= GFX8; /* 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; /* Out-of-order primitive rasterization. */ - device->has_out_of_order_rast = device->rad_info.chip_class >= VI && + device->has_out_of_order_rast = device->rad_info.chip_class >= GFX8 && device->rad_info.max_se >= 2; device->out_of_order_rast_allowed = device->has_out_of_order_rast && !(device->instance->debug_flags & RADV_DEBUG_NO_OUT_OF_ORDER); - device->dcc_msaa_allowed = device->rad_info.chip_class == VI && - (device->instance->perftest_flags & RADV_PERFTEST_DCC_MSAA); + device->dcc_msaa_allowed = + (device->instance->perftest_flags & RADV_PERFTEST_DCC_MSAA); + + /* TODO: Figure out how to use LOAD_CONTEXT_REG on GFX6-GFX7. */ + device->has_load_ctx_reg_pkt = device->rad_info.chip_class >= GFX9 || + (device->rad_info.chip_class >= GFX8 && + device->rad_info.me_fw_feature >= 41); + + device->use_shader_ballot = device->instance->perftest_flags & RADV_PERFTEST_SHADER_BALLOT; radv_physical_device_init_mem_types(device); radv_fill_device_extension_table(device, &device->supported_extensions); + device->bus_info = *drm_device->businfo.pci; + + if ((device->instance->debug_flags & RADV_DEBUG_INFO)) + ac_print_gpu_info(&device->rad_info); + + /* The WSI is structured as a layer on top of the driver, so this has + * to be the last part of initialization (at least until we get other + * semi-layers). + */ result = radv_init_wsi(device); if (result != VK_SUCCESS) { device->ws->destroy(device->ws); + vk_error(instance, result); goto fail; } - if ((device->instance->debug_flags & RADV_DEBUG_INFO)) - ac_print_gpu_info(&device->rad_info); - return VK_SUCCESS; fail: close(fd); + if (master_fd != -1) + close(master_fd); return result; } @@ -343,6 +408,8 @@ radv_physical_device_finish(struct radv_physical_device *device) device->ws->destroy(device->ws); disk_cache_destroy(device->disk_cache); close(device->local_fd); + if (device->master_fd != -1) + close(device->master_fd); } static void * @@ -392,6 +459,12 @@ static const struct debug_control radv_debug_options[] = { {"nodynamicbounds", RADV_DEBUG_NO_DYNAMIC_BOUNDS}, {"nooutoforder", RADV_DEBUG_NO_OUT_OF_ORDER}, {"info", RADV_DEBUG_INFO}, + {"errors", RADV_DEBUG_ERRORS}, + {"startup", RADV_DEBUG_STARTUP}, + {"checkir", RADV_DEBUG_CHECKIR}, + {"nothreadllvm", RADV_DEBUG_NOTHREADLLVM}, + {"nobinning", RADV_DEBUG_NOBINNING}, + {"noloadstoreopt", RADV_DEBUG_NO_LOAD_STORE_OPT}, {NULL, 0} }; @@ -406,15 +479,17 @@ 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}, {"dccmsaa", RADV_PERFTEST_DCC_MSAA}, + {"bolist", RADV_PERFTEST_BO_LIST}, + {"shader_ballot", RADV_PERFTEST_SHADER_BALLOT}, + {"tccompatcmask", RADV_PERFTEST_TC_COMPAT_CMASK}, {NULL, 0} }; const char * radv_get_perftest_option_name(int id) { - assert(id < ARRAY_SIZE(radv_debug_options) - 1); + assert(id < ARRAY_SIZE(radv_perftest_options) - 1); return radv_perftest_options[id].string; } @@ -435,6 +510,16 @@ radv_handle_per_app_options(struct radv_instance *instance, */ instance->perftest_flags |= RADV_PERFTEST_SISCHED; } + } else if (!strcmp(name, "DOOM_VFR")) { + /* Work around a Doom VFR game bug */ + instance->debug_flags |= RADV_DEBUG_NO_DYNAMIC_BOUNDS; + } else if (!strcmp(name, "MonsterHunterWorld.exe")) { + /* Workaround for a WaW hazard when LLVM moves/merges + * load/store memory operations. + * See https://reviews.llvm.org/D61313 + */ + if (HAVE_LLVM < 0x900) + instance->debug_flags |= RADV_DEBUG_NO_LOAD_STORE_OPT; } } @@ -447,6 +532,20 @@ static int radv_get_instance_extension_index(const char *name) return -1; } +static const char radv_dri_options_xml[] = +DRI_CONF_BEGIN + DRI_CONF_SECTION_QUALITY + DRI_CONF_ADAPTIVE_SYNC("true") + DRI_CONF_SECTION_END +DRI_CONF_END; + +static void radv_init_dri_options(struct radv_instance *instance) +{ + driParseOptionInfo(&instance->available_dri_options, radv_dri_options_xml); + driParseConfigFiles(&instance->dri_options, + &instance->available_dri_options, + 0, "radv", NULL); +} VkResult radv_CreateInstance( const VkInstanceCreateInfo* pCreateInfo, @@ -463,13 +562,13 @@ VkResult radv_CreateInstance( pCreateInfo->pApplicationInfo->apiVersion != 0) { client_version = pCreateInfo->pApplicationInfo->apiVersion; } else { - radv_EnumerateInstanceVersion(&client_version); + client_version = VK_API_VERSION_1_0; } instance = vk_zalloc2(&default_alloc, pAllocator, sizeof(*instance), 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (!instance) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); instance->_loader_data.loaderMagic = ICD_LOADER_MAGIC; @@ -481,13 +580,23 @@ VkResult radv_CreateInstance( instance->apiVersion = client_version; instance->physicalDeviceCount = -1; + instance->debug_flags = parse_debug_string(getenv("RADV_DEBUG"), + radv_debug_options); + + instance->perftest_flags = parse_debug_string(getenv("RADV_PERFTEST"), + radv_perftest_options); + + + if (instance->debug_flags & RADV_DEBUG_STARTUP) + radv_logi("Created an instance"); + for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i]; int index = radv_get_instance_extension_index(ext_name); if (index < 0 || !radv_supported_instance_extensions.extensions[index]) { vk_free2(&default_alloc, pAllocator, instance); - return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT); + return vk_error(instance, VK_ERROR_EXTENSION_NOT_PRESENT); } instance->enabled_extensions.extensions[index] = true; @@ -496,19 +605,15 @@ VkResult radv_CreateInstance( result = vk_debug_report_instance_init(&instance->debug_report_callbacks); if (result != VK_SUCCESS) { vk_free2(&default_alloc, pAllocator, instance); - return vk_error(result); + return vk_error(instance, result); } _mesa_locale_init(); + glsl_type_singleton_init_or_ref(); VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false)); - instance->debug_flags = parse_debug_string(getenv("RADV_DEBUG"), - radv_debug_options); - - instance->perftest_flags = parse_debug_string(getenv("RADV_PERFTEST"), - radv_perftest_options); - + radv_init_dri_options(instance); radv_handle_per_app_options(instance, pCreateInfo->pApplicationInfo); *pInstance = radv_instance_to_handle(instance); @@ -531,8 +636,12 @@ void radv_DestroyInstance( VG(VALGRIND_DESTROY_MEMPOOL(instance)); + glsl_type_singleton_decref(); _mesa_locale_fini(); + driDestroyOptionCache(&instance->dri_options); + driDestroyOptionInfo(&instance->available_dri_options); + vk_debug_report_instance_destroy(&instance->debug_report_callbacks); vk_free(&instance->alloc, instance); @@ -549,8 +658,12 @@ radv_enumerate_devices(struct radv_instance *instance) instance->physicalDeviceCount = 0; max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); + + if (instance->debug_flags & RADV_DEBUG_STARTUP) + radv_logi("Found %d drm nodes", max_devices); + if (max_devices < 1) - return vk_error(VK_ERROR_INCOMPATIBLE_DRIVER); + return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER); for (unsigned i = 0; i < (unsigned)max_devices; i++) { if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER && @@ -632,6 +745,7 @@ void radv_GetPhysicalDeviceFeatures( VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) { + RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); memset(pFeatures, 0, sizeof(*pFeatures)); *pFeatures = (VkPhysicalDeviceFeatures) { @@ -655,7 +769,7 @@ void radv_GetPhysicalDeviceFeatures( .alphaToOne = true, .multiViewport = true, .samplerAnisotropy = true, - .textureCompressionETC2 = false, + .textureCompressionETC2 = radv_device_supports_etc(pdevice), .textureCompressionASTC_LDR = false, .textureCompressionBC = true, .occlusionQueryPrecise = true, @@ -665,7 +779,7 @@ void radv_GetPhysicalDeviceFeatures( .shaderTessellationAndGeometryPointSize = true, .shaderImageGatherExtended = true, .shaderStorageImageExtendedFormats = true, - .shaderStorageImageMultisample = false, + .shaderStorageImageMultisample = pdevice->rad_info.chip_class >= GFX8, .shaderUniformBufferArrayDynamicIndexing = true, .shaderSampledImageArrayDynamicIndexing = true, .shaderStorageBufferArrayDynamicIndexing = true, @@ -676,7 +790,7 @@ void radv_GetPhysicalDeviceFeatures( .shaderCullDistance = true, .shaderFloat64 = true, .shaderInt64 = true, - .shaderInt16 = false, + .shaderInt16 = pdevice->rad_info.chip_class >= GFX9, .sparseBinding = true, .variableMultisampleRate = true, .inheritedQueries = true, @@ -685,26 +799,27 @@ void radv_GetPhysicalDeviceFeatures( void radv_GetPhysicalDeviceFeatures2( VkPhysicalDevice physicalDevice, - VkPhysicalDeviceFeatures2KHR *pFeatures) + VkPhysicalDeviceFeatures2 *pFeatures) { + RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); vk_foreach_struct(ext, pFeatures->pNext) { switch (ext->sType) { - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR: { - VkPhysicalDeviceVariablePointerFeaturesKHR *features = (void *)ext; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: { + VkPhysicalDeviceVariablePointersFeatures *features = (void *)ext; features->variablePointersStorageBuffer = true; - features->variablePointers = false; + features->variablePointers = true; break; } - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR: { - VkPhysicalDeviceMultiviewFeaturesKHR *features = (VkPhysicalDeviceMultiviewFeaturesKHR*)ext; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: { + VkPhysicalDeviceMultiviewFeatures *features = (VkPhysicalDeviceMultiviewFeatures*)ext; features->multiview = true; features->multiviewGeometryShader = true; features->multiviewTessellationShader = true; break; } - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES: { - VkPhysicalDeviceShaderDrawParameterFeatures *features = - (VkPhysicalDeviceShaderDrawParameterFeatures*)ext; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: { + VkPhysicalDeviceShaderDrawParametersFeatures *features = + (VkPhysicalDeviceShaderDrawParametersFeatures*)ext; features->shaderDrawParameters = true; break; } @@ -717,31 +832,32 @@ void radv_GetPhysicalDeviceFeatures2( case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: { VkPhysicalDevice16BitStorageFeatures *features = (VkPhysicalDevice16BitStorageFeatures*)ext; - features->storageBuffer16BitAccess = false; - features->uniformAndStorageBuffer16BitAccess = false; - features->storagePushConstant16 = false; - features->storageInputOutput16 = false; + bool enabled = pdevice->rad_info.chip_class >= GFX8; + features->storageBuffer16BitAccess = enabled; + features->uniformAndStorageBuffer16BitAccess = enabled; + features->storagePushConstant16 = enabled; + features->storageInputOutput16 = enabled && HAVE_LLVM >= 0x900; break; } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: { VkPhysicalDeviceSamplerYcbcrConversionFeatures *features = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)ext; - features->samplerYcbcrConversion = false; + features->samplerYcbcrConversion = true; break; } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: { VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features = - (VkPhysicalDeviceDescriptorIndexingFeaturesEXT*)features; + (VkPhysicalDeviceDescriptorIndexingFeaturesEXT*)ext; features->shaderInputAttachmentArrayDynamicIndexing = true; features->shaderUniformTexelBufferArrayDynamicIndexing = true; features->shaderStorageTexelBufferArrayDynamicIndexing = true; - features->shaderUniformBufferArrayNonUniformIndexing = false; - features->shaderSampledImageArrayNonUniformIndexing = false; - features->shaderStorageBufferArrayNonUniformIndexing = false; - features->shaderStorageImageArrayNonUniformIndexing = false; - features->shaderInputAttachmentArrayNonUniformIndexing = false; - features->shaderUniformTexelBufferArrayNonUniformIndexing = false; - features->shaderStorageTexelBufferArrayNonUniformIndexing = false; + features->shaderUniformBufferArrayNonUniformIndexing = true; + features->shaderSampledImageArrayNonUniformIndexing = true; + features->shaderStorageBufferArrayNonUniformIndexing = true; + features->shaderStorageImageArrayNonUniformIndexing = true; + features->shaderInputAttachmentArrayNonUniformIndexing = true; + features->shaderUniformTexelBufferArrayNonUniformIndexing = true; + features->shaderStorageTexelBufferArrayNonUniformIndexing = true; features->descriptorBindingUniformBufferUpdateAfterBind = true; features->descriptorBindingSampledImageUpdateAfterBind = true; features->descriptorBindingStorageImageUpdateAfterBind = true; @@ -754,6 +870,112 @@ void radv_GetPhysicalDeviceFeatures2( features->runtimeDescriptorArray = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: { + VkPhysicalDeviceConditionalRenderingFeaturesEXT *features = + (VkPhysicalDeviceConditionalRenderingFeaturesEXT*)ext; + features->conditionalRendering = true; + features->inheritedConditionalRendering = false; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: { + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features = + (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext; + features->vertexAttributeInstanceRateDivisor = VK_TRUE; + features->vertexAttributeInstanceRateZeroDivisor = VK_TRUE; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: { + VkPhysicalDeviceTransformFeedbackFeaturesEXT *features = + (VkPhysicalDeviceTransformFeedbackFeaturesEXT*)ext; + features->transformFeedback = true; + features->geometryStreams = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: { + VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *features = + (VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *)ext; + features->scalarBlockLayout = pdevice->rad_info.chip_class >= GFX7; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT: { + VkPhysicalDeviceMemoryPriorityFeaturesEXT *features = + (VkPhysicalDeviceMemoryPriorityFeaturesEXT *)ext; + features->memoryPriority = VK_TRUE; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT: { + VkPhysicalDeviceBufferDeviceAddressFeaturesEXT *features = + (VkPhysicalDeviceBufferDeviceAddressFeaturesEXT *)ext; + features->bufferDeviceAddress = true; + features->bufferDeviceAddressCaptureReplay = false; + features->bufferDeviceAddressMultiDevice = false; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: { + VkPhysicalDeviceDepthClipEnableFeaturesEXT *features = + (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext; + features->depthClipEnable = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: { + VkPhysicalDeviceHostQueryResetFeaturesEXT *features = + (VkPhysicalDeviceHostQueryResetFeaturesEXT *)ext; + features->hostQueryReset = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: { + VkPhysicalDevice8BitStorageFeaturesKHR *features = + (VkPhysicalDevice8BitStorageFeaturesKHR*)ext; + bool enabled = pdevice->rad_info.chip_class >= GFX8; + features->storageBuffer8BitAccess = enabled; + features->uniformAndStorageBuffer8BitAccess = enabled; + features->storagePushConstant8 = enabled; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR: { + VkPhysicalDeviceFloat16Int8FeaturesKHR *features = + (VkPhysicalDeviceFloat16Int8FeaturesKHR*)ext; + features->shaderFloat16 = pdevice->rad_info.chip_class >= GFX8 && HAVE_LLVM >= 0x0800; + features->shaderInt8 = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR: { + VkPhysicalDeviceShaderAtomicInt64FeaturesKHR *features = + (VkPhysicalDeviceShaderAtomicInt64FeaturesKHR *)ext; + /* TODO: Enable this once the driver supports 64-bit + * compare&swap atomic operations. + */ + features->shaderBufferInt64Atomics = false; + features->shaderSharedInt64Atomics = false; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT: { + VkPhysicalDeviceInlineUniformBlockFeaturesEXT *features = + (VkPhysicalDeviceInlineUniformBlockFeaturesEXT *)ext; + + features->inlineUniformBlock = true; + features->descriptorBindingInlineUniformBlockUpdateAfterBind = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV: { + VkPhysicalDeviceComputeShaderDerivativesFeaturesNV *features = + (VkPhysicalDeviceComputeShaderDerivativesFeaturesNV *)ext; + features->computeDerivativeGroupQuads = false; + features->computeDerivativeGroupLinear = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT: { + VkPhysicalDeviceYcbcrImageArraysFeaturesEXT *features = + (VkPhysicalDeviceYcbcrImageArraysFeaturesEXT*)ext; + features->ycbcrImageArrays = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR: { + VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR *features = + (VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR *)ext; + features->uniformBufferStandardLayout = true; + break; + } default: break; } @@ -811,8 +1033,8 @@ void radv_GetPhysicalDeviceProperties( .maxDescriptorSetSampledImages = max_descriptor_set_size, .maxDescriptorSetStorageImages = max_descriptor_set_size, .maxDescriptorSetInputAttachments = max_descriptor_set_size, - .maxVertexInputAttributes = 32, - .maxVertexInputBindings = 32, + .maxVertexInputAttributes = MAX_VERTEX_ATTRIBS, + .maxVertexInputBindings = MAX_VBS, .maxVertexInputAttributeOffset = 2047, .maxVertexInputBindingStride = 2048, .maxVertexOutputComponents = 128, @@ -841,9 +1063,9 @@ void radv_GetPhysicalDeviceProperties( 2048, 2048 }, - .subPixelPrecisionBits = 4 /* FIXME */, - .subTexelPrecisionBits = 4 /* FIXME */, - .mipmapPrecisionBits = 4 /* FIXME */, + .subPixelPrecisionBits = 8, + .subTexelPrecisionBits = 8, + .mipmapPrecisionBits = 8, .maxDrawIndexedIndexValue = UINT32_MAX, .maxDrawIndirectCount = UINT32_MAX, .maxSamplerLodBias = 16, @@ -875,15 +1097,15 @@ void radv_GetPhysicalDeviceProperties( .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT, .sampledImageDepthSampleCounts = sample_counts, .sampledImageStencilSampleCounts = sample_counts, - .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT, + .storageImageSampleCounts = pdevice->rad_info.chip_class >= GFX8 ? sample_counts : VK_SAMPLE_COUNT_1_BIT, .maxSampleMaskWords = 1, .timestampComputeAndGraphics = true, .timestampPeriod = 1000000.0 / pdevice->rad_info.clock_crystal_freq, .maxClipDistances = 8, .maxCullDistances = 8, .maxCombinedClipAndCullDistances = 8, - .discreteQueuePriorities = 1, - .pointSizeRange = { 0.125, 255.875 }, + .discreteQueuePriorities = 2, + .pointSizeRange = { 0.0, 8192.0 }, .lineWidthRange = { 0.0, 7.9921875 }, .pointSizeGranularity = (1.0 / 8.0), .lineWidthGranularity = (1.0 / 128.0), @@ -910,7 +1132,7 @@ void radv_GetPhysicalDeviceProperties( void radv_GetPhysicalDeviceProperties2( VkPhysicalDevice physicalDevice, - VkPhysicalDeviceProperties2KHR *pProperties) + VkPhysicalDeviceProperties2 *pProperties) { RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); radv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties); @@ -923,23 +1145,23 @@ void radv_GetPhysicalDeviceProperties2( properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS; break; } - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR: { - VkPhysicalDeviceIDPropertiesKHR *properties = (VkPhysicalDeviceIDPropertiesKHR*)ext; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: { + VkPhysicalDeviceIDProperties *properties = (VkPhysicalDeviceIDProperties*)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_KHR: { - VkPhysicalDeviceMultiviewPropertiesKHR *properties = (VkPhysicalDeviceMultiviewPropertiesKHR*)ext; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: { + VkPhysicalDeviceMultiviewProperties *properties = (VkPhysicalDeviceMultiviewProperties*)ext; properties->maxMultiviewViewCount = MAX_VIEWS; properties->maxMultiviewInstanceIndex = INT_MAX; break; } - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR: { - VkPhysicalDevicePointClippingPropertiesKHR *properties = - (VkPhysicalDevicePointClippingPropertiesKHR*)ext; - properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR; + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: { + VkPhysicalDevicePointClippingProperties *properties = + (VkPhysicalDevicePointClippingProperties*)ext; + properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES; break; } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT: { @@ -963,9 +1185,13 @@ void radv_GetPhysicalDeviceProperties2( VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT | VK_SUBGROUP_FEATURE_QUAD_BIT | - VK_SUBGROUP_FEATURE_SHUFFLE_BIT | - VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT; + if (pdevice->rad_info.chip_class >= GFX8) { + properties->supportedOperations |= + VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | + VK_SUBGROUP_FEATURE_SHUFFLE_BIT | + VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT; + } properties->quadOperationsInAllStages = true; break; } @@ -997,9 +1223,7 @@ void radv_GetPhysicalDeviceProperties2( properties->shaderArraysPerEngineCount = pdevice->rad_info.max_sh_per_se; properties->computeUnitsPerShaderArray = - pdevice->rad_info.num_good_compute_units / - (pdevice->rad_info.max_se * - pdevice->rad_info.max_sh_per_se); + pdevice->rad_info.num_good_cu_per_sh; properties->simdPerComputeUnit = 4; properties->wavefrontsPerSimd = pdevice->rad_info.family == CHIP_TONGA || @@ -1012,14 +1236,14 @@ void radv_GetPhysicalDeviceProperties2( /* SGPR. */ properties->sgprsPerSimd = - radv_get_num_physical_sgprs(pdevice); + ac_get_num_physical_sgprs(pdevice->rad_info.chip_class); properties->minSgprAllocation = - pdevice->rad_info.chip_class >= VI ? 16 : 8; + pdevice->rad_info.chip_class >= GFX8 ? 16 : 8; properties->maxSgprAllocation = pdevice->rad_info.family == CHIP_TONGA || pdevice->rad_info.family == CHIP_ICELAND ? 96 : 104; properties->sgprAllocationGranularity = - pdevice->rad_info.chip_class >= VI ? 16 : 8; + pdevice->rad_info.chip_class >= GFX8 ? 16 : 8; /* VGPR. */ properties->vgprsPerSimd = RADV_NUM_PHYSICAL_VGPRS; @@ -1046,7 +1270,8 @@ void radv_GetPhysicalDeviceProperties2( properties->robustBufferAccessUpdateAfterBind = false; properties->quadDivergentImplicitLod = false; - size_t max_descriptor_set_size = ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS) / + size_t max_descriptor_set_size = ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS - + MAX_INLINE_UNIFORM_BLOCK_SIZE * MAX_INLINE_UNIFORM_BLOCK_COUNT) / (32 /* uniform buffer, 32 due to potential space wasted on alignment */ + 32 /* storage buffer, 32 due to potential space wasted on alignment */ + 32 /* sampler, largest when combined with image */ + @@ -1069,6 +1294,95 @@ void radv_GetPhysicalDeviceProperties2( properties->maxDescriptorSetUpdateAfterBindInputAttachments = max_descriptor_set_size; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES: { + VkPhysicalDeviceProtectedMemoryProperties *properties = + (VkPhysicalDeviceProtectedMemoryProperties *)ext; + properties->protectedNoFault = false; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT: { + VkPhysicalDeviceConservativeRasterizationPropertiesEXT *properties = + (VkPhysicalDeviceConservativeRasterizationPropertiesEXT *)ext; + properties->primitiveOverestimationSize = 0; + properties->maxExtraPrimitiveOverestimationSize = 0; + properties->extraPrimitiveOverestimationSizeGranularity = 0; + properties->primitiveUnderestimation = VK_FALSE; + properties->conservativePointAndLineRasterization = VK_FALSE; + properties->degenerateTrianglesRasterized = VK_FALSE; + properties->degenerateLinesRasterized = VK_FALSE; + properties->fullyCoveredFragmentShaderInputVariable = VK_FALSE; + properties->conservativeRasterizationPostDepthCoverage = VK_FALSE; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: { + VkPhysicalDevicePCIBusInfoPropertiesEXT *properties = + (VkPhysicalDevicePCIBusInfoPropertiesEXT *)ext; + properties->pciDomain = pdevice->bus_info.domain; + properties->pciBus = pdevice->bus_info.bus; + properties->pciDevice = pdevice->bus_info.dev; + properties->pciFunction = pdevice->bus_info.func; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR: { + VkPhysicalDeviceDriverPropertiesKHR *driver_props = + (VkPhysicalDeviceDriverPropertiesKHR *) ext; + + driver_props->driverID = VK_DRIVER_ID_MESA_RADV_KHR; + memset(driver_props->driverName, 0, VK_MAX_DRIVER_NAME_SIZE_KHR); + strcpy(driver_props->driverName, "radv"); + + memset(driver_props->driverInfo, 0, VK_MAX_DRIVER_INFO_SIZE_KHR); + snprintf(driver_props->driverInfo, VK_MAX_DRIVER_INFO_SIZE_KHR, + "Mesa " PACKAGE_VERSION MESA_GIT_SHA1 + " (LLVM " MESA_LLVM_VERSION_STRING ")"); + + driver_props->conformanceVersion = (VkConformanceVersionKHR) { + .major = 1, + .minor = 1, + .subminor = 2, + .patch = 0, + }; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: { + VkPhysicalDeviceTransformFeedbackPropertiesEXT *properties = + (VkPhysicalDeviceTransformFeedbackPropertiesEXT *)ext; + properties->maxTransformFeedbackStreams = MAX_SO_STREAMS; + properties->maxTransformFeedbackBuffers = MAX_SO_BUFFERS; + properties->maxTransformFeedbackBufferSize = UINT32_MAX; + properties->maxTransformFeedbackStreamDataSize = 512; + properties->maxTransformFeedbackBufferDataSize = UINT32_MAX; + properties->maxTransformFeedbackBufferDataStride = 512; + properties->transformFeedbackQueries = true; + properties->transformFeedbackStreamsLinesTriangles = true; + properties->transformFeedbackRasterizationStreamSelect = false; + properties->transformFeedbackDraw = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT: { + VkPhysicalDeviceInlineUniformBlockPropertiesEXT *props = + (VkPhysicalDeviceInlineUniformBlockPropertiesEXT *)ext; + + props->maxInlineUniformBlockSize = MAX_INLINE_UNIFORM_BLOCK_SIZE; + props->maxPerStageDescriptorInlineUniformBlocks = MAX_INLINE_UNIFORM_BLOCK_SIZE * MAX_SETS; + props->maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks = MAX_INLINE_UNIFORM_BLOCK_SIZE * MAX_SETS; + props->maxDescriptorSetInlineUniformBlocks = MAX_INLINE_UNIFORM_BLOCK_COUNT; + props->maxDescriptorSetUpdateAfterBindInlineUniformBlocks = MAX_INLINE_UNIFORM_BLOCK_COUNT; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: { + VkPhysicalDeviceSampleLocationsPropertiesEXT *properties = + (VkPhysicalDeviceSampleLocationsPropertiesEXT *)ext; + properties->sampleLocationSampleCounts = VK_SAMPLE_COUNT_2_BIT | + VK_SAMPLE_COUNT_4_BIT | + VK_SAMPLE_COUNT_8_BIT; + properties->maxSampleLocationGridSize = (VkExtent2D){ 2 , 2 }; + properties->sampleLocationCoordinateRange[0] = 0.0f; + properties->sampleLocationCoordinateRange[1] = 0.9375f; + properties->sampleLocationSubPixelBits = 4; + properties->variableSampleLocations = VK_FALSE; + break; + } default: break; } @@ -1132,7 +1446,7 @@ void radv_GetPhysicalDeviceQueueFamilyProperties( { RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); if (!pQueueFamilyProperties) { - return radv_get_physical_device_queue_family_properties(pdevice, pCount, NULL); + radv_get_physical_device_queue_family_properties(pdevice, pCount, NULL); return; } VkQueueFamilyProperties *properties[] = { @@ -1147,11 +1461,11 @@ void radv_GetPhysicalDeviceQueueFamilyProperties( void radv_GetPhysicalDeviceQueueFamilyProperties2( VkPhysicalDevice physicalDevice, uint32_t* pCount, - VkQueueFamilyProperties2KHR *pQueueFamilyProperties) + VkQueueFamilyProperties2 *pQueueFamilyProperties) { RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); if (!pQueueFamilyProperties) { - return radv_get_physical_device_queue_family_properties(pdevice, pCount, NULL); + radv_get_physical_device_queue_family_properties(pdevice, pCount, NULL); return; } VkQueueFamilyProperties *properties[] = { @@ -1172,17 +1486,95 @@ void radv_GetPhysicalDeviceMemoryProperties( *pMemoryProperties = physical_device->memory_properties; } +static void +radv_get_memory_budget_properties(VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryBudgetPropertiesEXT *memoryBudget) +{ + RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); + VkPhysicalDeviceMemoryProperties *memory_properties = &device->memory_properties; + uint64_t visible_vram_size = radv_get_visible_vram_size(device); + uint64_t vram_size = radv_get_vram_size(device); + uint64_t gtt_size = device->rad_info.gart_size; + uint64_t heap_budget, heap_usage; + + /* For all memory heaps, the computation of budget is as follow: + * heap_budget = heap_size - global_heap_usage + app_heap_usage + * + * The Vulkan spec 1.1.97 says that the budget should include any + * currently allocated device memory. + * + * Note that the application heap usages are not really accurate (eg. + * in presence of shared buffers). + */ + for (int i = 0; i < device->memory_properties.memoryTypeCount; i++) { + uint32_t heap_index = device->memory_properties.memoryTypes[i].heapIndex; + + switch (device->mem_type_indices[i]) { + case RADV_MEM_TYPE_VRAM: + heap_usage = device->ws->query_value(device->ws, + RADEON_ALLOCATED_VRAM); + + heap_budget = vram_size - + device->ws->query_value(device->ws, RADEON_VRAM_USAGE) + + heap_usage; + + memoryBudget->heapBudget[heap_index] = heap_budget; + memoryBudget->heapUsage[heap_index] = heap_usage; + break; + case RADV_MEM_TYPE_VRAM_CPU_ACCESS: + heap_usage = device->ws->query_value(device->ws, + RADEON_ALLOCATED_VRAM_VIS); + + heap_budget = visible_vram_size - + device->ws->query_value(device->ws, RADEON_VRAM_VIS_USAGE) + + heap_usage; + + memoryBudget->heapBudget[heap_index] = heap_budget; + memoryBudget->heapUsage[heap_index] = heap_usage; + break; + case RADV_MEM_TYPE_GTT_WRITE_COMBINE: + heap_usage = device->ws->query_value(device->ws, + RADEON_ALLOCATED_GTT); + + heap_budget = gtt_size - + device->ws->query_value(device->ws, RADEON_GTT_USAGE) + + heap_usage; + + memoryBudget->heapBudget[heap_index] = heap_budget; + memoryBudget->heapUsage[heap_index] = heap_usage; + break; + default: + break; + } + } + + /* The heapBudget and heapUsage values must be zero for array elements + * greater than or equal to + * VkPhysicalDeviceMemoryProperties::memoryHeapCount. + */ + for (uint32_t i = memory_properties->memoryHeapCount; i < VK_MAX_MEMORY_HEAPS; i++) { + memoryBudget->heapBudget[i] = 0; + memoryBudget->heapUsage[i] = 0; + } +} + void radv_GetPhysicalDeviceMemoryProperties2( VkPhysicalDevice physicalDevice, - VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties) + VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) { - return radv_GetPhysicalDeviceMemoryProperties(physicalDevice, - &pMemoryProperties->memoryProperties); + radv_GetPhysicalDeviceMemoryProperties(physicalDevice, + &pMemoryProperties->memoryProperties); + + VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget = + vk_find_struct(pMemoryProperties->pNext, + PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT); + if (memory_budget) + radv_get_memory_budget_properties(physicalDevice, memory_budget); } VkResult radv_GetMemoryHostPointerPropertiesEXT( VkDevice _device, - VkExternalMemoryHandleTypeFlagBitsKHR handleType, + VkExternalMemoryHandleTypeFlagBits handleType, const void *pHostPointer, VkMemoryHostPointerPropertiesEXT *pMemoryHostPointerProperties) { @@ -1203,7 +1595,7 @@ VkResult radv_GetMemoryHostPointerPropertiesEXT( return VK_SUCCESS; } default: - return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR; + return VK_ERROR_INVALID_EXTERNAL_HANDLE; } } @@ -1244,7 +1636,7 @@ radv_queue_init(struct radv_device *device, struct radv_queue *queue, queue->hw_ctx = device->ws->ctx_create(device->ws, queue->priority); if (!queue->hw_ctx) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); return VK_SUCCESS; } @@ -1295,6 +1687,9 @@ static VkResult radv_bo_list_add(struct radv_device *device, { struct radv_bo_list *bo_list = &device->bo_list; + if (bo->is_local) + return VK_SUCCESS; + if (unlikely(!device->use_global_bo_list)) return VK_SUCCESS; @@ -1322,6 +1717,9 @@ static void radv_bo_list_remove(struct radv_device *device, { struct radv_bo_list *bo_list = &device->bo_list; + if (bo->is_local) + return; + if (unlikely(!device->use_global_bo_list)) return; @@ -1352,6 +1750,28 @@ static int radv_get_device_extension_index(const char *name) return -1; } +static int +radv_get_int_debug_option(const char *name, int default_value) +{ + const char *str; + int result; + + str = getenv(name); + if (!str) { + result = default_value; + } else { + char *endptr; + + result = strtol(str, &endptr, 0); + if (str == endptr) { + /* No digits founs. */ + result = default_value; + } + } + + return result; +} + VkResult radv_CreateDevice( VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, @@ -1373,7 +1793,7 @@ VkResult radv_CreateDevice( 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); + return vk_error(physical_device->instance, VK_ERROR_FEATURE_NOT_PRESENT); } } @@ -1381,7 +1801,7 @@ VkResult radv_CreateDevice( sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); if (!device) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); device->_loader_data.loaderMagic = ICD_LOADER_MAGIC; device->instance = physical_device->instance; @@ -1398,7 +1818,7 @@ VkResult radv_CreateDevice( int index = radv_get_device_extension_index(ext_name); if (index < 0 || !physical_device->supported_extensions.extensions[index]) { vk_free(&device->alloc, device); - return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT); + return vk_error(physical_device->instance, VK_ERROR_EXTENSION_NOT_PRESENT); } device->enabled_extensions.extensions[index] = true; @@ -1410,7 +1830,9 @@ VkResult radv_CreateDevice( * from the descriptor set anymore, so we have to use a global BO list. */ device->use_global_bo_list = - device->enabled_extensions.EXT_descriptor_indexing; + (device->instance->perftest_flags & RADV_PERFTEST_BO_LIST) || + device->enabled_extensions.EXT_descriptor_indexing || + device->enabled_extensions.EXT_buffer_device_address; mtx_init(&device->shader_slab_mutex, mtx_plain); list_inithead(&device->shader_slabs); @@ -1446,10 +1868,12 @@ VkResult radv_CreateDevice( } device->pbb_allowed = device->physical_device->rad_info.chip_class >= GFX9 && - (device->instance->perftest_flags & RADV_PERFTEST_BINNING); + !(device->instance->debug_flags & RADV_DEBUG_NOBINNING); /* Disabled and not implemented for now. */ - device->dfsm_allowed = device->pbb_allowed && false; + device->dfsm_allowed = device->pbb_allowed && + (device->physical_device->rad_info.family == CHIP_RAVEN || + device->physical_device->rad_info.family == CHIP_RAVEN2); #ifdef ANDROID device->always_use_syncobj = device->physical_device->rad_info.has_syncobj_wait_for_submit; @@ -1473,7 +1897,7 @@ VkResult radv_CreateDevice( device->dispatch_initiator = S_00B800_COMPUTE_SHADER_EN(1); - if (device->physical_device->rad_info.chip_class >= CIK) { + if (device->physical_device->rad_info.chip_class >= GFX7) { /* If the KMD allows it (there is a KMD hw register for it), * allow launching waves out-of-order. */ @@ -1485,7 +1909,7 @@ VkResult radv_CreateDevice( device->tess_offchip_block_dw_size = device->physical_device->rad_info.family == CHIP_HAWAII ? 4096 : 8192; device->has_distributed_tess = - device->physical_device->rad_info.chip_class >= VI && + device->physical_device->rad_info.chip_class >= GFX8 && device->physical_device->rad_info.max_se >= 2; if (getenv("RADV_TRACE_FILE")) { @@ -1496,6 +1920,10 @@ VkResult radv_CreateDevice( if (!radv_init_trace(device)) goto fail; + fprintf(stderr, "*****************************************************************************\n"); + fprintf(stderr, "* WARNING: RADV_TRACE_FILE is costly and should only be used for debugging! *\n"); + fprintf(stderr, "*****************************************************************************\n"); + fprintf(stderr, "Trace file will be dumped to %s\n", filename); radv_dump_enabled_options(device, stderr); } @@ -1524,7 +1952,7 @@ VkResult radv_CreateDevice( device->ws->cs_finalize(device->empty_cs[family]); } - if (device->physical_device->rad_info.chip_class >= CIK) + if (device->physical_device->rad_info.chip_class >= GFX7) cik_create_gfx_config(device); VkPipelineCacheCreateInfo ci; @@ -1541,6 +1969,13 @@ VkResult radv_CreateDevice( device->mem_cache = radv_pipeline_cache_from_handle(pc); + device->force_aniso = + MIN2(16, radv_get_int_debug_option("RADV_TEX_ANISO", -1)); + if (device->force_aniso >= 0) { + fprintf(stderr, "radv: Forcing anisotropy filter to %ix\n", + 1 << util_logbase2(device->force_aniso)); + } + *pDevice = radv_device_to_handle(device); return VK_SUCCESS; @@ -1610,7 +2045,7 @@ VkResult radv_EnumerateInstanceLayerProperties( } /* None supported at this time */ - return vk_error(VK_ERROR_LAYER_NOT_PRESENT); + return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); } VkResult radv_EnumerateDeviceLayerProperties( @@ -1624,7 +2059,7 @@ VkResult radv_EnumerateDeviceLayerProperties( } /* None supported at this time */ - return vk_error(VK_ERROR_LAYER_NOT_PRESENT); + return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); } void radv_GetDeviceQueue2( @@ -1680,167 +2115,188 @@ fill_geom_tess_rings(struct radv_queue *queue, uint32_t tess_offchip_ring_size, struct radeon_winsys_bo *tess_rings_bo) { - uint64_t esgs_va = 0, gsvs_va = 0; - uint64_t tess_va = 0, tess_offchip_va = 0; uint32_t *desc = &map[4]; - if (esgs_ring_bo) - esgs_va = radv_buffer_get_va(esgs_ring_bo); - if (gsvs_ring_bo) - gsvs_va = radv_buffer_get_va(gsvs_ring_bo); + if (esgs_ring_bo) { + uint64_t esgs_va = radv_buffer_get_va(esgs_ring_bo); + + /* stride 0, num records - size, add tid, swizzle, elsize4, + index stride 64 */ + desc[0] = esgs_va; + desc[1] = S_008F04_BASE_ADDRESS_HI(esgs_va >> 32) | + S_008F04_STRIDE(0) | + S_008F04_SWIZZLE_ENABLE(true); + desc[2] = esgs_ring_size; + desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | + S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | + S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | + S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | + S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | + S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | + S_008F0C_ELEMENT_SIZE(1) | + S_008F0C_INDEX_STRIDE(3) | + S_008F0C_ADD_TID_ENABLE(true); + + /* GS entry for ES->GS ring */ + /* stride 0, num records - size, elsize0, + index stride 0 */ + desc[4] = esgs_va; + desc[5] = S_008F04_BASE_ADDRESS_HI(esgs_va >> 32)| + S_008F04_STRIDE(0) | + S_008F04_SWIZZLE_ENABLE(false); + desc[6] = esgs_ring_size; + desc[7] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | + S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | + S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | + S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | + S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | + S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | + S_008F0C_ELEMENT_SIZE(0) | + S_008F0C_INDEX_STRIDE(0) | + S_008F0C_ADD_TID_ENABLE(false); + } + + desc += 8; + + if (gsvs_ring_bo) { + uint64_t gsvs_va = radv_buffer_get_va(gsvs_ring_bo); + + /* VS entry for GS->VS ring */ + /* stride 0, num records - size, elsize0, + index stride 0 */ + desc[0] = gsvs_va; + desc[1] = S_008F04_BASE_ADDRESS_HI(gsvs_va >> 32)| + S_008F04_STRIDE(0) | + S_008F04_SWIZZLE_ENABLE(false); + desc[2] = gsvs_ring_size; + desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | + S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | + S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | + S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | + S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | + S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | + S_008F0C_ELEMENT_SIZE(0) | + S_008F0C_INDEX_STRIDE(0) | + S_008F0C_ADD_TID_ENABLE(false); + + /* stride gsvs_itemsize, num records 64 + elsize 4, index stride 16 */ + /* shader will patch stride and desc[2] */ + desc[4] = gsvs_va; + desc[5] = S_008F04_BASE_ADDRESS_HI(gsvs_va >> 32)| + S_008F04_STRIDE(0) | + S_008F04_SWIZZLE_ENABLE(true); + desc[6] = 0; + desc[7] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | + S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | + S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | + S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | + S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | + S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | + S_008F0C_ELEMENT_SIZE(1) | + S_008F0C_INDEX_STRIDE(1) | + S_008F0C_ADD_TID_ENABLE(true); + } + + desc += 8; + if (tess_rings_bo) { - tess_va = radv_buffer_get_va(tess_rings_bo); - tess_offchip_va = tess_va + tess_offchip_ring_offset; - } - - /* stride 0, num records - size, add tid, swizzle, elsize4, - index stride 64 */ - desc[0] = esgs_va; - desc[1] = S_008F04_BASE_ADDRESS_HI(esgs_va >> 32) | - S_008F04_STRIDE(0) | - S_008F04_SWIZZLE_ENABLE(true); - desc[2] = esgs_ring_size; - desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | - S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | - S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | - S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | - S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | - S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | - S_008F0C_ELEMENT_SIZE(1) | - S_008F0C_INDEX_STRIDE(3) | - S_008F0C_ADD_TID_ENABLE(true); - - desc += 4; - /* GS entry for ES->GS ring */ - /* stride 0, num records - size, elsize0, - index stride 0 */ - desc[0] = esgs_va; - desc[1] = S_008F04_BASE_ADDRESS_HI(esgs_va >> 32)| - S_008F04_STRIDE(0) | - S_008F04_SWIZZLE_ENABLE(false); - desc[2] = esgs_ring_size; - desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | - S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | - S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | - S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | - S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | - S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | - S_008F0C_ELEMENT_SIZE(0) | - S_008F0C_INDEX_STRIDE(0) | - S_008F0C_ADD_TID_ENABLE(false); - - desc += 4; - /* VS entry for GS->VS ring */ - /* stride 0, num records - size, elsize0, - index stride 0 */ - desc[0] = gsvs_va; - desc[1] = S_008F04_BASE_ADDRESS_HI(gsvs_va >> 32)| - S_008F04_STRIDE(0) | - S_008F04_SWIZZLE_ENABLE(false); - desc[2] = gsvs_ring_size; - desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | - S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | - S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | - S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | - S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | - S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | - S_008F0C_ELEMENT_SIZE(0) | - S_008F0C_INDEX_STRIDE(0) | - S_008F0C_ADD_TID_ENABLE(false); - desc += 4; - - /* stride gsvs_itemsize, num records 64 - elsize 4, index stride 16 */ - /* shader will patch stride and desc[2] */ - desc[0] = gsvs_va; - desc[1] = S_008F04_BASE_ADDRESS_HI(gsvs_va >> 32)| - S_008F04_STRIDE(0) | - S_008F04_SWIZZLE_ENABLE(true); - desc[2] = 0; - desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | - S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | - S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | - S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | - S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | - S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | - S_008F0C_ELEMENT_SIZE(1) | - S_008F0C_INDEX_STRIDE(1) | - S_008F0C_ADD_TID_ENABLE(true); - desc += 4; - - desc[0] = tess_va; - desc[1] = S_008F04_BASE_ADDRESS_HI(tess_va >> 32) | - S_008F04_STRIDE(0) | - S_008F04_SWIZZLE_ENABLE(false); - desc[2] = tess_factor_ring_size; - desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | - S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | - S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | - S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | - S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | - S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | - S_008F0C_ELEMENT_SIZE(0) | - S_008F0C_INDEX_STRIDE(0) | - S_008F0C_ADD_TID_ENABLE(false); - desc += 4; - - desc[0] = tess_offchip_va; - desc[1] = S_008F04_BASE_ADDRESS_HI(tess_offchip_va >> 32) | - S_008F04_STRIDE(0) | - S_008F04_SWIZZLE_ENABLE(false); - desc[2] = tess_offchip_ring_size; - desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | - S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | - S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | - S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | - S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | - S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | - S_008F0C_ELEMENT_SIZE(0) | - S_008F0C_INDEX_STRIDE(0) | - S_008F0C_ADD_TID_ENABLE(false); - desc += 4; - - /* add sample positions after all rings */ - memcpy(desc, queue->device->sample_locations_1x, 8); - desc += 2; - memcpy(desc, queue->device->sample_locations_2x, 16); - desc += 4; - memcpy(desc, queue->device->sample_locations_4x, 32); + uint64_t tess_va = radv_buffer_get_va(tess_rings_bo); + uint64_t tess_offchip_va = tess_va + tess_offchip_ring_offset; + + desc[0] = tess_va; + desc[1] = S_008F04_BASE_ADDRESS_HI(tess_va >> 32) | + S_008F04_STRIDE(0) | + S_008F04_SWIZZLE_ENABLE(false); + desc[2] = tess_factor_ring_size; + desc[3] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | + S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | + S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | + S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | + S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | + S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | + S_008F0C_ELEMENT_SIZE(0) | + S_008F0C_INDEX_STRIDE(0) | + S_008F0C_ADD_TID_ENABLE(false); + + desc[4] = tess_offchip_va; + desc[5] = S_008F04_BASE_ADDRESS_HI(tess_offchip_va >> 32) | + S_008F04_STRIDE(0) | + S_008F04_SWIZZLE_ENABLE(false); + desc[6] = tess_offchip_ring_size; + desc[7] = S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) | + S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) | + S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) | + S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) | + S_008F0C_NUM_FORMAT(V_008F0C_BUF_NUM_FORMAT_FLOAT) | + S_008F0C_DATA_FORMAT(V_008F0C_BUF_DATA_FORMAT_32) | + S_008F0C_ELEMENT_SIZE(0) | + S_008F0C_INDEX_STRIDE(0) | + S_008F0C_ADD_TID_ENABLE(false); + } + desc += 8; - memcpy(desc, queue->device->sample_locations_8x, 64); - desc += 16; - memcpy(desc, queue->device->sample_locations_16x, 128); + + if (add_sample_positions) { + /* add sample positions after all rings */ + memcpy(desc, queue->device->sample_locations_1x, 8); + desc += 2; + memcpy(desc, queue->device->sample_locations_2x, 16); + desc += 4; + memcpy(desc, queue->device->sample_locations_4x, 32); + desc += 8; + memcpy(desc, queue->device->sample_locations_8x, 64); + } } static unsigned radv_get_hs_offchip_param(struct radv_device *device, uint32_t *max_offchip_buffers_p) { - bool double_offchip_buffers = device->physical_device->rad_info.chip_class >= CIK && + bool double_offchip_buffers = device->physical_device->rad_info.chip_class >= GFX7 && device->physical_device->rad_info.family != CHIP_CARRIZO && device->physical_device->rad_info.family != CHIP_STONEY; unsigned max_offchip_buffers_per_se = double_offchip_buffers ? 128 : 64; - unsigned max_offchip_buffers = max_offchip_buffers_per_se * - device->physical_device->rad_info.max_se; + unsigned max_offchip_buffers; unsigned offchip_granularity; unsigned hs_offchip_param; - switch (device->tess_offchip_block_dw_size) { - default: - assert(0); - /* fall through */ - case 8192: - offchip_granularity = V_03093C_X_8K_DWORDS; - break; - case 4096: + + /* + * Per RadeonSI: + * This must be one less than the maximum number due to a hw limitation. + * Various hardware bugs need thGFX7 + * + * Per AMDVLK: + * Vega10 should limit max_offchip_buffers to 508 (4 * 127). + * Gfx7 should limit max_offchip_buffers to 508 + * Gfx6 should limit max_offchip_buffers to 126 (2 * 63) + * + * Follow AMDVLK here. + */ + if (device->physical_device->rad_info.family == CHIP_VEGA10 || + device->physical_device->rad_info.chip_class == GFX7 || + device->physical_device->rad_info.chip_class == GFX6) + --max_offchip_buffers_per_se; + + max_offchip_buffers = max_offchip_buffers_per_se * + device->physical_device->rad_info.max_se; + + /* Hawaii has a bug with offchip buffers > 256 that can be worked + * around by setting 4K granularity. + */ + if (device->tess_offchip_block_dw_size == 4096) { + assert(device->physical_device->rad_info.family == CHIP_HAWAII); offchip_granularity = V_03093C_X_4K_DWORDS; - break; + } else { + assert(device->tess_offchip_block_dw_size == 8192); + offchip_granularity = V_03093C_X_8K_DWORDS; } switch (device->physical_device->rad_info.chip_class) { - case SI: + case GFX6: max_offchip_buffers = MIN2(max_offchip_buffers, 126); break; - case CIK: - case VI: + case GFX7: + case GFX8: case GFX9: default: max_offchip_buffers = MIN2(max_offchip_buffers, 508); @@ -1848,8 +2304,8 @@ radv_get_hs_offchip_param(struct radv_device *device, uint32_t *max_offchip_buff } *max_offchip_buffers_p = max_offchip_buffers; - if (device->physical_device->rad_info.chip_class >= CIK) { - if (device->physical_device->rad_info.chip_class >= VI) + if (device->physical_device->rad_info.chip_class >= GFX7) { + if (device->physical_device->rad_info.chip_class >= GFX8) --max_offchip_buffers; hs_offchip_param = S_03093C_OFFCHIP_BUFFERING(max_offchip_buffers) | @@ -1861,6 +2317,153 @@ radv_get_hs_offchip_param(struct radv_device *device, uint32_t *max_offchip_buff return hs_offchip_param; } +static void +radv_emit_gs_ring_sizes(struct radv_queue *queue, struct radeon_cmdbuf *cs, + struct radeon_winsys_bo *esgs_ring_bo, + uint32_t esgs_ring_size, + struct radeon_winsys_bo *gsvs_ring_bo, + uint32_t gsvs_ring_size) +{ + if (!esgs_ring_bo && !gsvs_ring_bo) + return; + + if (esgs_ring_bo) + radv_cs_add_buffer(queue->device->ws, cs, esgs_ring_bo); + + if (gsvs_ring_bo) + radv_cs_add_buffer(queue->device->ws, cs, gsvs_ring_bo); + + if (queue->device->physical_device->rad_info.chip_class >= GFX7) { + radeon_set_uconfig_reg_seq(cs, R_030900_VGT_ESGS_RING_SIZE, 2); + radeon_emit(cs, esgs_ring_size >> 8); + radeon_emit(cs, gsvs_ring_size >> 8); + } else { + radeon_set_config_reg_seq(cs, R_0088C8_VGT_ESGS_RING_SIZE, 2); + radeon_emit(cs, esgs_ring_size >> 8); + radeon_emit(cs, gsvs_ring_size >> 8); + } +} + +static void +radv_emit_tess_factor_ring(struct radv_queue *queue, struct radeon_cmdbuf *cs, + unsigned hs_offchip_param, unsigned tf_ring_size, + struct radeon_winsys_bo *tess_rings_bo) +{ + uint64_t tf_va; + + if (!tess_rings_bo) + return; + + tf_va = radv_buffer_get_va(tess_rings_bo); + + radv_cs_add_buffer(queue->device->ws, cs, tess_rings_bo); + + if (queue->device->physical_device->rad_info.chip_class >= GFX7) { + radeon_set_uconfig_reg(cs, R_030938_VGT_TF_RING_SIZE, + S_030938_SIZE(tf_ring_size / 4)); + radeon_set_uconfig_reg(cs, R_030940_VGT_TF_MEMORY_BASE, + tf_va >> 8); + if (queue->device->physical_device->rad_info.chip_class >= GFX9) { + radeon_set_uconfig_reg(cs, R_030944_VGT_TF_MEMORY_BASE_HI, + S_030944_BASE_HI(tf_va >> 40)); + } + radeon_set_uconfig_reg(cs, R_03093C_VGT_HS_OFFCHIP_PARAM, + hs_offchip_param); + } else { + radeon_set_config_reg(cs, R_008988_VGT_TF_RING_SIZE, + S_008988_SIZE(tf_ring_size / 4)); + radeon_set_config_reg(cs, R_0089B8_VGT_TF_MEMORY_BASE, + tf_va >> 8); + radeon_set_config_reg(cs, R_0089B0_VGT_HS_OFFCHIP_PARAM, + hs_offchip_param); + } +} + +static void +radv_emit_compute_scratch(struct radv_queue *queue, struct radeon_cmdbuf *cs, + struct radeon_winsys_bo *compute_scratch_bo) +{ + uint64_t scratch_va; + + if (!compute_scratch_bo) + return; + + scratch_va = radv_buffer_get_va(compute_scratch_bo); + + radv_cs_add_buffer(queue->device->ws, cs, compute_scratch_bo); + + radeon_set_sh_reg_seq(cs, R_00B900_COMPUTE_USER_DATA_0, 2); + radeon_emit(cs, scratch_va); + radeon_emit(cs, S_008F04_BASE_ADDRESS_HI(scratch_va >> 32) | + S_008F04_SWIZZLE_ENABLE(1)); +} + +static void +radv_emit_global_shader_pointers(struct radv_queue *queue, + struct radeon_cmdbuf *cs, + struct radeon_winsys_bo *descriptor_bo) +{ + uint64_t va; + + if (!descriptor_bo) + return; + + va = radv_buffer_get_va(descriptor_bo); + + radv_cs_add_buffer(queue->device->ws, cs, descriptor_bo); + + if (queue->device->physical_device->rad_info.chip_class >= GFX9) { + uint32_t regs[] = {R_00B030_SPI_SHADER_USER_DATA_PS_0, + R_00B130_SPI_SHADER_USER_DATA_VS_0, + R_00B208_SPI_SHADER_USER_DATA_ADDR_LO_GS, + R_00B408_SPI_SHADER_USER_DATA_ADDR_LO_HS}; + + for (int i = 0; i < ARRAY_SIZE(regs); ++i) { + radv_emit_shader_pointer(queue->device, cs, regs[i], + va, true); + } + } else { + uint32_t regs[] = {R_00B030_SPI_SHADER_USER_DATA_PS_0, + R_00B130_SPI_SHADER_USER_DATA_VS_0, + R_00B230_SPI_SHADER_USER_DATA_GS_0, + R_00B330_SPI_SHADER_USER_DATA_ES_0, + R_00B430_SPI_SHADER_USER_DATA_HS_0, + R_00B530_SPI_SHADER_USER_DATA_LS_0}; + + for (int i = 0; i < ARRAY_SIZE(regs); ++i) { + radv_emit_shader_pointer(queue->device, cs, regs[i], + va, true); + } + } +} + +static void +radv_init_graphics_state(struct radeon_cmdbuf *cs, struct radv_queue *queue) +{ + struct radv_device *device = queue->device; + + if (device->gfx_init) { + uint64_t va = radv_buffer_get_va(device->gfx_init); + + radeon_emit(cs, PKT3(PKT3_INDIRECT_BUFFER_CIK, 2, 0)); + radeon_emit(cs, va); + radeon_emit(cs, va >> 32); + radeon_emit(cs, device->gfx_init_size_dw & 0xffff); + + radv_cs_add_buffer(device->ws, cs, device->gfx_init); + } else { + struct radv_physical_device *physical_device = device->physical_device; + si_emit_graphics(physical_device, cs); + } +} + +static void +radv_init_compute_state(struct radeon_cmdbuf *cs, struct radv_queue *queue) +{ + struct radv_physical_device *physical_device = queue->device->physical_device; + si_emit_compute(physical_device, cs); +} + static VkResult radv_get_preamble_cs(struct radv_queue *queue, uint32_t scratch_size, @@ -1869,9 +2472,9 @@ radv_get_preamble_cs(struct radv_queue *queue, uint32_t gsvs_ring_size, bool needs_tess_rings, bool needs_sample_positions, - struct radeon_winsys_cs **initial_full_flush_preamble_cs, - struct radeon_winsys_cs **initial_preamble_cs, - struct radeon_winsys_cs **continue_preamble_cs) + struct radeon_cmdbuf **initial_full_flush_preamble_cs, + struct radeon_cmdbuf **initial_preamble_cs, + struct radeon_cmdbuf **continue_preamble_cs) { struct radeon_winsys_bo *scratch_bo = NULL; struct radeon_winsys_bo *descriptor_bo = NULL; @@ -1879,7 +2482,7 @@ radv_get_preamble_cs(struct radv_queue *queue, struct radeon_winsys_bo *esgs_ring_bo = NULL; struct radeon_winsys_bo *gsvs_ring_bo = NULL; struct radeon_winsys_bo *tess_rings_bo = NULL; - struct radeon_winsys_cs *dest_cs[3] = {0}; + struct radeon_cmdbuf *dest_cs[3] = {0}; bool add_tess_rings = false, add_sample_positions = false; unsigned tess_factor_ring_size = 0, tess_offchip_ring_size = 0; unsigned max_offchip_buffers; @@ -1920,7 +2523,8 @@ radv_get_preamble_cs(struct radv_queue *queue, scratch_size, 4096, RADEON_DOMAIN_VRAM, - ring_bo_flags); + ring_bo_flags, + RADV_BO_PRIORITY_SCRATCH); if (!scratch_bo) goto fail; } else @@ -1931,7 +2535,8 @@ radv_get_preamble_cs(struct radv_queue *queue, compute_scratch_size, 4096, RADEON_DOMAIN_VRAM, - ring_bo_flags); + ring_bo_flags, + RADV_BO_PRIORITY_SCRATCH); if (!compute_scratch_bo) goto fail; @@ -1943,7 +2548,8 @@ radv_get_preamble_cs(struct radv_queue *queue, esgs_ring_size, 4096, RADEON_DOMAIN_VRAM, - ring_bo_flags); + ring_bo_flags, + RADV_BO_PRIORITY_SCRATCH); if (!esgs_ring_bo) goto fail; } else { @@ -1956,7 +2562,8 @@ radv_get_preamble_cs(struct radv_queue *queue, gsvs_ring_size, 4096, RADEON_DOMAIN_VRAM, - ring_bo_flags); + ring_bo_flags, + RADV_BO_PRIORITY_SCRATCH); if (!gsvs_ring_bo) goto fail; } else { @@ -1969,7 +2576,8 @@ radv_get_preamble_cs(struct radv_queue *queue, tess_offchip_ring_offset + tess_offchip_ring_size, 256, RADEON_DOMAIN_VRAM, - ring_bo_flags); + ring_bo_flags, + RADV_BO_PRIORITY_SCRATCH); if (!tess_rings_bo) goto fail; } else { @@ -1986,7 +2594,7 @@ radv_get_preamble_cs(struct radv_queue *queue, tess_rings_bo || add_sample_positions) { size = 112; /* 2 dword + 2 padding + 4 dword * 6 */ if (add_sample_positions) - size += 256; /* 32+16+8+4+2+1 samples * 4 * 2 = 248 bytes. */ + size += 128; /* 64+32+16+8 = 120 bytes */ } else if (scratch_bo) size = 8; /* 2 dword */ @@ -1997,14 +2605,38 @@ radv_get_preamble_cs(struct radv_queue *queue, RADEON_DOMAIN_VRAM, RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING | - RADEON_FLAG_READ_ONLY); + RADEON_FLAG_READ_ONLY, + RADV_BO_PRIORITY_DESCRIPTOR); if (!descriptor_bo) goto fail; } else descriptor_bo = queue->descriptor_bo; + if (descriptor_bo != queue->descriptor_bo) { + uint32_t *map = (uint32_t*)queue->device->ws->buffer_map(descriptor_bo); + + if (scratch_bo) { + uint64_t scratch_va = radv_buffer_get_va(scratch_bo); + uint32_t rsrc1 = S_008F04_BASE_ADDRESS_HI(scratch_va >> 32) | + S_008F04_SWIZZLE_ENABLE(1); + map[0] = scratch_va; + map[1] = rsrc1; + } + + if (esgs_ring_bo || gsvs_ring_bo || tess_rings_bo || add_sample_positions) + fill_geom_tess_rings(queue, map, add_sample_positions, + esgs_ring_size, esgs_ring_bo, + gsvs_ring_size, gsvs_ring_bo, + tess_factor_ring_size, + tess_offchip_ring_offset, + tess_offchip_ring_size, + tess_rings_bo); + + queue->device->ws->buffer_unmap(descriptor_bo); + } + for(int i = 0; i < 3; ++i) { - struct radeon_winsys_cs *cs = NULL; + struct radeon_cmdbuf *cs = NULL; cs = queue->device->ws->cs_create(queue->device->ws, queue->queue_family_index ? RING_COMPUTE : RING_GFX); if (!cs) @@ -2013,42 +2645,18 @@ radv_get_preamble_cs(struct radv_queue *queue, dest_cs[i] = cs; if (scratch_bo) - radv_cs_add_buffer(queue->device->ws, cs, scratch_bo, 8); + radv_cs_add_buffer(queue->device->ws, cs, scratch_bo); - if (esgs_ring_bo) - radv_cs_add_buffer(queue->device->ws, cs, esgs_ring_bo, 8); - - if (gsvs_ring_bo) - radv_cs_add_buffer(queue->device->ws, cs, gsvs_ring_bo, 8); - - if (tess_rings_bo) - radv_cs_add_buffer(queue->device->ws, cs, tess_rings_bo, 8); - - if (descriptor_bo) - radv_cs_add_buffer(queue->device->ws, cs, descriptor_bo, 8); - - if (descriptor_bo != queue->descriptor_bo) { - uint32_t *map = (uint32_t*)queue->device->ws->buffer_map(descriptor_bo); - - if (scratch_bo) { - uint64_t scratch_va = radv_buffer_get_va(scratch_bo); - uint32_t rsrc1 = S_008F04_BASE_ADDRESS_HI(scratch_va >> 32) | - S_008F04_SWIZZLE_ENABLE(1); - map[0] = scratch_va; - map[1] = rsrc1; - } - - if (esgs_ring_bo || gsvs_ring_bo || tess_rings_bo || - add_sample_positions) - fill_geom_tess_rings(queue, map, add_sample_positions, - esgs_ring_size, esgs_ring_bo, - gsvs_ring_size, gsvs_ring_bo, - tess_factor_ring_size, - tess_offchip_ring_offset, - tess_offchip_ring_size, - tess_rings_bo); - - queue->device->ws->buffer_unmap(descriptor_bo); + /* Emit initial configuration. */ + switch (queue->queue_family_index) { + case RADV_QUEUE_GENERAL: + radv_init_graphics_state(cs, queue); + break; + case RADV_QUEUE_COMPUTE: + radv_init_compute_state(cs, queue); + break; + case RADV_QUEUE_TRANSFER: + break; } if (esgs_ring_bo || gsvs_ring_bo || tess_rings_bo) { @@ -2058,102 +2666,36 @@ radv_get_preamble_cs(struct radv_queue *queue, radeon_emit(cs, EVENT_TYPE(V_028A90_VGT_FLUSH) | EVENT_INDEX(0)); } - if (esgs_ring_bo || gsvs_ring_bo) { - if (queue->device->physical_device->rad_info.chip_class >= CIK) { - radeon_set_uconfig_reg_seq(cs, R_030900_VGT_ESGS_RING_SIZE, 2); - radeon_emit(cs, esgs_ring_size >> 8); - radeon_emit(cs, gsvs_ring_size >> 8); - } else { - radeon_set_config_reg_seq(cs, R_0088C8_VGT_ESGS_RING_SIZE, 2); - radeon_emit(cs, esgs_ring_size >> 8); - radeon_emit(cs, gsvs_ring_size >> 8); - } - } - - if (tess_rings_bo) { - uint64_t tf_va = radv_buffer_get_va(tess_rings_bo); - if (queue->device->physical_device->rad_info.chip_class >= CIK) { - radeon_set_uconfig_reg(cs, R_030938_VGT_TF_RING_SIZE, - S_030938_SIZE(tess_factor_ring_size / 4)); - radeon_set_uconfig_reg(cs, R_030940_VGT_TF_MEMORY_BASE, - tf_va >> 8); - if (queue->device->physical_device->rad_info.chip_class >= GFX9) { - radeon_set_uconfig_reg(cs, R_030944_VGT_TF_MEMORY_BASE_HI, - S_030944_BASE_HI(tf_va >> 40)); - } - radeon_set_uconfig_reg(cs, R_03093C_VGT_HS_OFFCHIP_PARAM, hs_offchip_param); - } else { - radeon_set_config_reg(cs, R_008988_VGT_TF_RING_SIZE, - S_008988_SIZE(tess_factor_ring_size / 4)); - radeon_set_config_reg(cs, R_0089B8_VGT_TF_MEMORY_BASE, - tf_va >> 8); - radeon_set_config_reg(cs, R_0089B0_VGT_HS_OFFCHIP_PARAM, - hs_offchip_param); - } - } - - if (descriptor_bo) { - uint64_t va = radv_buffer_get_va(descriptor_bo); - if (queue->device->physical_device->rad_info.chip_class >= GFX9) { - uint32_t regs[] = {R_00B030_SPI_SHADER_USER_DATA_PS_0, - R_00B130_SPI_SHADER_USER_DATA_VS_0, - R_00B208_SPI_SHADER_USER_DATA_ADDR_LO_GS, - R_00B408_SPI_SHADER_USER_DATA_ADDR_LO_HS}; - - for (int i = 0; i < ARRAY_SIZE(regs); ++i) { - radeon_set_sh_reg_seq(cs, regs[i], 2); - radeon_emit(cs, va); - radeon_emit(cs, va >> 32); - } - } else { - uint32_t regs[] = {R_00B030_SPI_SHADER_USER_DATA_PS_0, - R_00B130_SPI_SHADER_USER_DATA_VS_0, - R_00B230_SPI_SHADER_USER_DATA_GS_0, - R_00B330_SPI_SHADER_USER_DATA_ES_0, - R_00B430_SPI_SHADER_USER_DATA_HS_0, - R_00B530_SPI_SHADER_USER_DATA_LS_0}; - - for (int i = 0; i < ARRAY_SIZE(regs); ++i) { - radeon_set_sh_reg_seq(cs, regs[i], 2); - radeon_emit(cs, va); - radeon_emit(cs, va >> 32); - } - } - } - - if (compute_scratch_bo) { - uint64_t scratch_va = radv_buffer_get_va(compute_scratch_bo); - uint32_t rsrc1 = S_008F04_BASE_ADDRESS_HI(scratch_va >> 32) | - S_008F04_SWIZZLE_ENABLE(1); - - radv_cs_add_buffer(queue->device->ws, cs, compute_scratch_bo, 8); - - radeon_set_sh_reg_seq(cs, R_00B900_COMPUTE_USER_DATA_0, 2); - radeon_emit(cs, scratch_va); - radeon_emit(cs, rsrc1); - } + radv_emit_gs_ring_sizes(queue, cs, esgs_ring_bo, esgs_ring_size, + gsvs_ring_bo, gsvs_ring_size); + radv_emit_tess_factor_ring(queue, cs, hs_offchip_param, + tess_factor_ring_size, tess_rings_bo); + radv_emit_global_shader_pointers(queue, cs, descriptor_bo); + radv_emit_compute_scratch(queue, cs, compute_scratch_bo); if (i == 0) { si_cs_emit_cache_flush(cs, queue->device->physical_device->rad_info.chip_class, NULL, 0, queue->queue_family_index == RING_COMPUTE && - queue->device->physical_device->rad_info.chip_class >= CIK, + queue->device->physical_device->rad_info.chip_class >= GFX7, (queue->queue_family_index == RADV_QUEUE_COMPUTE ? RADV_CMD_FLAG_CS_PARTIAL_FLUSH : (RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_PS_PARTIAL_FLUSH)) | RADV_CMD_FLAG_INV_ICACHE | RADV_CMD_FLAG_INV_SMEM_L1 | RADV_CMD_FLAG_INV_VMEM_L1 | - RADV_CMD_FLAG_INV_GLOBAL_L2); + RADV_CMD_FLAG_INV_GLOBAL_L2 | + RADV_CMD_FLAG_START_PIPELINE_STATS, 0); } else if (i == 1) { si_cs_emit_cache_flush(cs, queue->device->physical_device->rad_info.chip_class, NULL, 0, queue->queue_family_index == RING_COMPUTE && - queue->device->physical_device->rad_info.chip_class >= CIK, + queue->device->physical_device->rad_info.chip_class >= GFX7, RADV_CMD_FLAG_INV_ICACHE | RADV_CMD_FLAG_INV_SMEM_L1 | RADV_CMD_FLAG_INV_VMEM_L1 | - RADV_CMD_FLAG_INV_GLOBAL_L2); + RADV_CMD_FLAG_INV_GLOBAL_L2 | + RADV_CMD_FLAG_START_PIPELINE_STATS, 0); } if (!queue->device->ws->cs_finalize(cs)) @@ -2238,10 +2780,11 @@ fail: queue->device->ws->buffer_destroy(gsvs_ring_bo); if (tess_rings_bo && tess_rings_bo != queue->tess_rings_bo) queue->device->ws->buffer_destroy(tess_rings_bo); - return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY); + return vk_error(queue->device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY); } -static VkResult radv_alloc_sem_counts(struct radv_winsys_sem_counts *counts, +static VkResult radv_alloc_sem_counts(struct radv_instance *instance, + struct radv_winsys_sem_counts *counts, int num_sems, const VkSemaphore *sems, VkFence _fence, @@ -2270,14 +2813,14 @@ static VkResult radv_alloc_sem_counts(struct radv_winsys_sem_counts *counts, if (counts->syncobj_count) { counts->syncobj = (uint32_t *)malloc(sizeof(uint32_t) * counts->syncobj_count); if (!counts->syncobj) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(instance, 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(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); } } @@ -2306,7 +2849,8 @@ static VkResult radv_alloc_sem_counts(struct radv_winsys_sem_counts *counts, return VK_SUCCESS; } -void radv_free_sem_info(struct radv_winsys_sem_info *sem_info) +static void +radv_free_sem_info(struct radv_winsys_sem_info *sem_info) { free(sem_info->wait.syncobj); free(sem_info->wait.sem); @@ -2329,20 +2873,22 @@ static void radv_free_temp_syncobjs(struct radv_device *device, } } -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, - VkFence fence) +static VkResult +radv_alloc_sem_info(struct radv_instance *instance, + struct radv_winsys_sem_info *sem_info, + int num_wait_sems, + const VkSemaphore *wait_sems, + int num_signal_sems, + const VkSemaphore *signal_sems, + VkFence fence) { VkResult ret; memset(sem_info, 0, sizeof(*sem_info)); - ret = radv_alloc_sem_counts(&sem_info->wait, num_wait_sems, wait_sems, VK_NULL_HANDLE, true); + ret = radv_alloc_sem_counts(instance, &sem_info->wait, num_wait_sems, wait_sems, VK_NULL_HANDLE, true); if (ret) return ret; - ret = radv_alloc_sem_counts(&sem_info->signal, num_signal_sems, signal_sems, fence, false); + ret = radv_alloc_sem_counts(instance, &sem_info->signal, num_signal_sems, signal_sems, fence, false); if (ret) radv_free_sem_info(sem_info); @@ -2360,7 +2906,7 @@ static VkResult radv_signal_fence(struct radv_queue *queue, VkResult result; struct radv_winsys_sem_info sem_info; - result = radv_alloc_sem_info(&sem_info, 0, NULL, 0, NULL, + result = radv_alloc_sem_info(queue->device->instance, &sem_info, 0, NULL, 0, NULL, radv_fence_to_handle(fence)); if (result != VK_SUCCESS) return result; @@ -2371,9 +2917,8 @@ static VkResult radv_signal_fence(struct radv_queue *queue, false, fence->fence); radv_free_sem_info(&sem_info); - /* TODO: find a better error */ if (ret) - return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY); + return vk_error(queue->device->instance, VK_ERROR_DEVICE_LOST); return VK_SUCCESS; } @@ -2389,11 +2934,11 @@ VkResult radv_QueueSubmit( struct radeon_winsys_fence *base_fence = fence ? fence->fence : NULL; struct radeon_winsys_ctx *ctx = queue->hw_ctx; int ret; - uint32_t max_cs_submission = queue->device->trace_bo ? 1 : UINT32_MAX; + uint32_t max_cs_submission = queue->device->trace_bo ? 1 : RADV_MAX_IBS_PER_SUBMIT; uint32_t scratch_size = 0; uint32_t compute_scratch_size = 0; uint32_t esgs_ring_size = 0, gsvs_ring_size = 0; - struct radeon_winsys_cs *initial_preamble_cs = NULL, *initial_flush_preamble_cs = NULL, *continue_preamble_cs = NULL; + struct radeon_cmdbuf *initial_preamble_cs = NULL, *initial_flush_preamble_cs = NULL, *continue_preamble_cs = NULL; VkResult result; bool fence_emitted = false; bool tess_rings_needed = false; @@ -2424,13 +2969,14 @@ VkResult radv_QueueSubmit( return result; for (uint32_t i = 0; i < submitCount; i++) { - struct radeon_winsys_cs **cs_array; + struct radeon_cmdbuf **cs_array; bool do_flush = !i || pSubmits[i].pWaitDstStageMask; bool can_patch = true; uint32_t advance; struct radv_winsys_sem_info sem_info; - result = radv_alloc_sem_info(&sem_info, + result = radv_alloc_sem_info(queue->device->instance, + &sem_info, pSubmits[i].waitSemaphoreCount, pSubmits[i].pWaitSemaphores, pSubmits[i].signalSemaphoreCount, @@ -2456,7 +3002,7 @@ VkResult radv_QueueSubmit( continue; } - cs_array = malloc(sizeof(struct radeon_winsys_cs *) * + cs_array = malloc(sizeof(struct radeon_cmdbuf *) * (pSubmits[i].commandBufferCount)); for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) { @@ -2472,7 +3018,7 @@ VkResult radv_QueueSubmit( } for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j += advance) { - struct radeon_winsys_cs *initial_preamble = (do_flush && !j) ? initial_flush_preamble_cs : initial_preamble_cs; + struct radeon_cmdbuf *initial_preamble = (do_flush && !j) ? initial_flush_preamble_cs : initial_preamble_cs; const struct radv_winsys_bo_list *bo_list = NULL; advance = MIN2(max_cs_submission, @@ -2516,9 +3062,10 @@ VkResult radv_QueueSubmit( if (fence) { if (!fence_emitted) { - radv_signal_fence(queue, fence); + result = radv_signal_fence(queue, fence); + if (result != VK_SUCCESS) + return result; } - fence->submitted = true; } return VK_SUCCESS; @@ -2614,6 +3161,23 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr( return radv_GetInstanceProcAddr(instance, pName); } +PUBLIC +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr( + VkInstance _instance, + const char* pName); + +PUBLIC +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr( + VkInstance _instance, + const char* pName) +{ + RADV_FROM_HANDLE(radv_instance, instance, _instance); + + return radv_lookup_physical_device_entrypoint_checked(pName, + instance ? instance->apiVersion : 0, + instance ? &instance->enabled_extensions : NULL); +} + PFN_vkVoidFunction radv_GetDeviceProcAddr( VkDevice _device, const char* pName) @@ -2662,10 +3226,10 @@ static VkResult radv_alloc_memory(struct radv_device *device, 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); - const VkExportMemoryAllocateInfoKHR *export_info = - vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO_KHR); + const VkMemoryDedicatedAllocateInfo *dedicate_info = + vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO); + const VkExportMemoryAllocateInfo *export_info = + vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO); const VkImportMemoryHostPointerInfoEXT *host_ptr_info = vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_HOST_POINTER_INFO_EXT); @@ -2675,7 +3239,7 @@ static VkResult radv_alloc_memory(struct radv_device *device, mem = vk_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (mem == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); if (wsi_info && wsi_info->implicit_sync) flags |= RADEON_FLAG_IMPLICIT_SYNC; @@ -2688,17 +3252,27 @@ static VkResult radv_alloc_memory(struct radv_device *device, mem->buffer = NULL; } + float priority_float = 0.5; + const struct VkMemoryPriorityAllocateInfoEXT *priority_ext = + vk_find_struct_const(pAllocateInfo->pNext, + MEMORY_PRIORITY_ALLOCATE_INFO_EXT); + if (priority_ext) + priority_float = priority_ext->priority; + + unsigned priority = MIN2(RADV_BO_PRIORITY_APPLICATION_MAX - 1, + (int)(priority_float * RADV_BO_PRIORITY_APPLICATION_MAX)); + mem->user_ptr = NULL; if (import_info) { assert(import_info->handleType == - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR || + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || import_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); mem->bo = device->ws->buffer_from_fd(device->ws, import_info->fd, - NULL, NULL); + priority, NULL, NULL); if (!mem->bo) { - result = VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR; + result = VK_ERROR_INVALID_EXTERNAL_HANDLE; goto fail; } else { close(import_info->fd); @@ -2707,9 +3281,10 @@ static VkResult radv_alloc_memory(struct radv_device *device, assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT); assert(mem_type_index == RADV_MEM_TYPE_GTT_CACHED); mem->bo = device->ws->buffer_from_ptr(device->ws, host_ptr_info->pHostPointer, - pAllocateInfo->allocationSize); + pAllocateInfo->allocationSize, + priority); if (!mem->bo) { - result = VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR; + result = VK_ERROR_INVALID_EXTERNAL_HANDLE; goto fail; } else { mem->user_ptr = host_ptr_info->pHostPointer; @@ -2730,11 +3305,15 @@ static VkResult radv_alloc_memory(struct radv_device *device, if (mem_type_index == RADV_MEM_TYPE_GTT_WRITE_COMBINE) flags |= RADEON_FLAG_GTT_WC; - if (!dedicate_info && !import_info && (!export_info || !export_info->handleTypes)) + if (!dedicate_info && !import_info && (!export_info || !export_info->handleTypes)) { flags |= RADEON_FLAG_NO_INTERPROCESS_SHARING; + if (device->use_global_bo_list) { + flags |= RADEON_FLAG_PREFER_LOCAL_BO; + } + } mem->bo = device->ws->buffer_create(device->ws, alloc_size, device->physical_device->rad_info.max_alignment, - domain, flags); + domain, flags, priority); if (!mem->bo) { result = VK_ERROR_OUT_OF_DEVICE_MEMORY; @@ -2813,7 +3392,7 @@ VkResult radv_MapMemory( return VK_SUCCESS; } - return vk_error(VK_ERROR_MEMORY_MAP_FAILED); + return vk_error(device->instance, VK_ERROR_MEMORY_MAP_FAILED); } void radv_UnmapMemory( @@ -2866,17 +3445,17 @@ void radv_GetBufferMemoryRequirements( void radv_GetBufferMemoryRequirements2( VkDevice device, - const VkBufferMemoryRequirementsInfo2KHR* pInfo, - VkMemoryRequirements2KHR* pMemoryRequirements) + const VkBufferMemoryRequirementsInfo2 *pInfo, + VkMemoryRequirements2 *pMemoryRequirements) { radv_GetBufferMemoryRequirements(device, pInfo->buffer, &pMemoryRequirements->memoryRequirements); RADV_FROM_HANDLE(radv_buffer, buffer, pInfo->buffer); vk_foreach_struct(ext, pMemoryRequirements->pNext) { switch (ext->sType) { - case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR: { - VkMemoryDedicatedRequirementsKHR *req = - (VkMemoryDedicatedRequirementsKHR *) ext; + case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { + VkMemoryDedicatedRequirements *req = + (VkMemoryDedicatedRequirements *) ext; req->requiresDedicatedAllocation = buffer->shareable; req->prefersDedicatedAllocation = req->requiresDedicatedAllocation; break; @@ -2903,8 +3482,8 @@ void radv_GetImageMemoryRequirements( void radv_GetImageMemoryRequirements2( VkDevice device, - const VkImageMemoryRequirementsInfo2KHR* pInfo, - VkMemoryRequirements2KHR* pMemoryRequirements) + const VkImageMemoryRequirementsInfo2 *pInfo, + VkMemoryRequirements2 *pMemoryRequirements) { radv_GetImageMemoryRequirements(device, pInfo->image, &pMemoryRequirements->memoryRequirements); @@ -2913,9 +3492,9 @@ void radv_GetImageMemoryRequirements2( vk_foreach_struct(ext, pMemoryRequirements->pNext) { switch (ext->sType) { - case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR: { - VkMemoryDedicatedRequirementsKHR *req = - (VkMemoryDedicatedRequirementsKHR *) ext; + case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { + VkMemoryDedicatedRequirements *req = + (VkMemoryDedicatedRequirements *) ext; req->requiresDedicatedAllocation = image->shareable; req->prefersDedicatedAllocation = req->requiresDedicatedAllocation; break; @@ -2937,9 +3516,9 @@ void radv_GetImageSparseMemoryRequirements( void radv_GetImageSparseMemoryRequirements2( VkDevice device, - const VkImageSparseMemoryRequirementsInfo2KHR* pInfo, + const VkImageSparseMemoryRequirementsInfo2 *pInfo, uint32_t* pSparseMemoryRequirementCount, - VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements) + VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements) { stub(); } @@ -2954,7 +3533,7 @@ void radv_GetDeviceMemoryCommitment( VkResult radv_BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, - const VkBindBufferMemoryInfoKHR *pBindInfos) + const VkBindBufferMemoryInfo *pBindInfos) { for (uint32_t i = 0; i < bindInfoCount; ++i) { RADV_FROM_HANDLE(radv_device_memory, mem, pBindInfos[i].memory); @@ -2976,8 +3555,8 @@ VkResult radv_BindBufferMemory( VkDeviceMemory memory, VkDeviceSize memoryOffset) { - const VkBindBufferMemoryInfoKHR info = { - .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR, + const VkBindBufferMemoryInfo info = { + .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, .buffer = buffer, .memory = memory, .memoryOffset = memoryOffset @@ -2988,7 +3567,7 @@ VkResult radv_BindBufferMemory( VkResult radv_BindImageMemory2(VkDevice device, uint32_t bindInfoCount, - const VkBindImageMemoryInfoKHR *pBindInfos) + const VkBindImageMemoryInfo *pBindInfos) { for (uint32_t i = 0; i < bindInfoCount; ++i) { RADV_FROM_HANDLE(radv_device_memory, mem, pBindInfos[i].memory); @@ -3012,8 +3591,8 @@ VkResult radv_BindImageMemory( VkDeviceMemory memory, VkDeviceSize memoryOffset) { - const VkBindImageMemoryInfoKHR info = { - .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR, + const VkBindImageMemoryInfo info = { + .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, .image = image, .memory = memory, .memoryOffset = memoryOffset @@ -3073,6 +3652,8 @@ radv_sparse_image_opaque_bind_memory(struct radv_device *device, RADV_FROM_HANDLE(radv_queue, queue, _queue); struct radeon_winsys_fence *base_fence = fence ? fence->fence : NULL; bool fence_emitted = false; + VkResult result; + int ret; for (uint32_t i = 0; i < bindInfoCount; ++i) { struct radv_winsys_sem_info sem_info; @@ -3087,7 +3668,8 @@ radv_sparse_image_opaque_bind_memory(struct radv_device *device, } VkResult result; - result = radv_alloc_sem_info(&sem_info, + result = radv_alloc_sem_info(queue->device->instance, + &sem_info, pBindInfo[i].waitSemaphoreCount, pBindInfo[i].pWaitSemaphores, pBindInfo[i].signalSemaphoreCount, @@ -3097,14 +3679,17 @@ radv_sparse_image_opaque_bind_memory(struct radv_device *device, 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, - &sem_info, NULL, - false, base_fence); + ret = queue->device->ws->cs_submit(queue->hw_ctx, queue->queue_idx, + &queue->device->empty_cs[queue->queue_family_index], + 1, NULL, NULL, + &sem_info, NULL, + false, base_fence); + if (ret) { + radv_loge("failed to submit CS %d\n", i); + abort(); + } + fence_emitted = true; - if (fence) - fence->submitted = true; } radv_free_sem_info(&sem_info); @@ -3113,9 +3698,10 @@ radv_sparse_image_opaque_bind_memory(struct radv_device *device, if (fence) { if (!fence_emitted) { - radv_signal_fence(queue, fence); + result = radv_signal_fence(queue, fence); + if (result != VK_SUCCESS) + return result; } - fence->submitted = true; } return VK_SUCCESS; @@ -3128,9 +3714,9 @@ VkResult radv_CreateFence( VkFence* pFence) { RADV_FROM_HANDLE(radv_device, device, _device); - const VkExportFenceCreateInfoKHR *export = - vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO_KHR); - VkExternalFenceHandleTypeFlagsKHR handleTypes = + const VkExportFenceCreateInfo *export = + vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO); + VkExternalFenceHandleTypeFlags handleTypes = export ? export->handleTypes : 0; struct radv_fence *fence = vk_alloc2(&device->alloc, pAllocator, @@ -3138,16 +3724,15 @@ VkResult radv_CreateFence( VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!fence) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); - fence->submitted = false; - fence->signalled = !!(pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT); + fence->fence_wsi = NULL; fence->temp_syncobj = 0; if (device->always_use_syncobj || handleTypes) { int ret = device->ws->create_syncobj(device->ws, &fence->syncobj); if (ret) { vk_free2(&device->alloc, pAllocator, fence); - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); } if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) { device->ws->signal_syncobj(device->ws, fence->syncobj); @@ -3157,9 +3742,11 @@ VkResult radv_CreateFence( fence->fence = device->ws->create_fence(); if (!fence->fence) { vk_free2(&device->alloc, pAllocator, fence); - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); } fence->syncobj = 0; + if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) + device->ws->signal_fence(fence->fence); } *pFence = radv_fence_to_handle(fence); @@ -3184,11 +3771,13 @@ void radv_DestroyFence( device->ws->destroy_syncobj(device->ws, fence->syncobj); if (fence->fence) device->ws->destroy_fence(fence->fence); + if (fence->fence_wsi) + fence->fence_wsi->destroy(fence->fence_wsi); vk_free2(&device->alloc, pAllocator, fence); } -static uint64_t radv_get_current_time() +uint64_t radv_get_current_time(void) { struct timespec tv; clock_gettime(CLOCK_MONOTONIC, &tv); @@ -3205,11 +3794,24 @@ static uint64_t radv_get_absolute_timeout(uint64_t timeout) } -static bool radv_all_fences_plain_and_submitted(uint32_t fenceCount, const VkFence *pFences) +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]); - if (fence->syncobj || fence->temp_syncobj || (!fence->signalled && !fence->submitted)) + if (fence->fence == NULL || fence->syncobj || + fence->temp_syncobj || fence->fence_wsi || + (!device->ws->is_fence_waitable(fence->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) { + RADV_FROM_HANDLE(radv_fence, fence, pFences[i]); + if (fence->syncobj == 0 && fence->temp_syncobj == 0) return false; } return true; @@ -3225,10 +3827,12 @@ VkResult radv_WaitForFences( RADV_FROM_HANDLE(radv_device, device, _device); timeout = radv_get_absolute_timeout(timeout); - if (device->always_use_syncobj) { + if (device->always_use_syncobj && + radv_all_fences_syncobj(fenceCount, pFences)) + { uint32_t *handles = malloc(sizeof(uint32_t) * fenceCount); if (!handles) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + 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]); @@ -3243,16 +3847,16 @@ 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(fenceCount, pFences)) { + 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(VK_ERROR_OUT_OF_HOST_MEMORY); + 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]); - if (fence->signalled) { + if (device->ws->fence_wait(device->ws, fence->fence, false, 0)) { free(fences); return VK_SUCCESS; } @@ -3292,26 +3896,25 @@ VkResult radv_WaitForFences( continue; } - if (fence->signalled) - continue; - - if (!fence->submitted) { - while(radv_get_current_time() <= timeout && !fence->submitted) - /* Do nothing */; + if (fence->fence) { + if (!device->ws->is_fence_waitable(fence->fence)) { + while(!device->ws->is_fence_waitable(fence->fence) && + radv_get_current_time() <= timeout) + /* Do nothing */; + } - if (!fence->submitted) + expired = device->ws->fence_wait(device->ws, + fence->fence, + true, timeout); + if (!expired) return VK_TIMEOUT; - - /* Recheck as it may have been set by submitting operations. */ - if (fence->signalled) - continue; } - expired = device->ws->fence_wait(device->ws, fence->fence, true, timeout); - if (!expired) - return VK_TIMEOUT; - - fence->signalled = true; + if (fence->fence_wsi) { + VkResult result = fence->fence_wsi->wait(fence->fence_wsi, timeout); + if (result != VK_SUCCESS) + return result; + } } return VK_SUCCESS; @@ -3325,7 +3928,8 @@ VkResult radv_ResetFences(VkDevice _device, for (unsigned i = 0; i < fenceCount; ++i) { RADV_FROM_HANDLE(radv_fence, fence, pFences[i]); - fence->submitted = fence->signalled = false; + if (fence->fence) + device->ws->reset_fence(fence->fence); /* Per spec, we first restore the permanent payload, and then reset, so * having a temp syncobj should not skip resetting the permanent syncobj. */ @@ -3357,13 +3961,19 @@ VkResult radv_GetFenceStatus(VkDevice _device, VkFence _fence) return success ? VK_SUCCESS : VK_NOT_READY; } - if (fence->signalled) - return VK_SUCCESS; - if (!fence->submitted) - return VK_NOT_READY; - if (!device->ws->fence_wait(device->ws, fence->fence, false, 0)) - return VK_NOT_READY; + if (fence->fence) { + if (!device->ws->fence_wait(device->ws, fence->fence, false, 0)) + return VK_NOT_READY; + } + if (fence->fence_wsi) { + VkResult result = fence->fence_wsi->wait(fence->fence_wsi, 0); + if (result != VK_SUCCESS) { + if (result == VK_TIMEOUT) + return VK_NOT_READY; + return result; + } + } return VK_SUCCESS; } @@ -3377,16 +3987,16 @@ VkResult radv_CreateSemaphore( VkSemaphore* pSemaphore) { RADV_FROM_HANDLE(radv_device, device, _device); - const VkExportSemaphoreCreateInfoKHR *export = - vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO_KHR); - VkExternalSemaphoreHandleTypeFlagsKHR handleTypes = + const VkExportSemaphoreCreateInfo *export = + vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO); + VkExternalSemaphoreHandleTypeFlags handleTypes = export ? export->handleTypes : 0; struct radv_semaphore *sem = vk_alloc2(&device->alloc, pAllocator, sizeof(*sem), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!sem) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); sem->temp_syncobj = 0; /* create a syncobject if we are going to export this semaphore */ @@ -3395,14 +4005,14 @@ VkResult radv_CreateSemaphore( int ret = device->ws->create_syncobj(device->ws, &sem->syncobj); if (ret) { vk_free2(&device->alloc, pAllocator, sem); - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, 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(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); } sem->syncobj = 0; } @@ -3440,14 +4050,15 @@ VkResult radv_CreateEvent( VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!event) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); event->bo = device->ws->buffer_create(device->ws, 8, 8, RADEON_DOMAIN_GTT, - RADEON_FLAG_VA_UNCACHED | RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING); + RADEON_FLAG_VA_UNCACHED | RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING, + RADV_BO_PRIORITY_FENCE); if (!event->bo) { vk_free2(&device->alloc, pAllocator, event); - return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY); } event->map = (uint64_t*)device->ws->buffer_map(event->bo); @@ -3516,7 +4127,7 @@ VkResult radv_CreateBuffer( buffer = vk_alloc2(&device->alloc, pAllocator, sizeof(*buffer), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (buffer == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); buffer->size = pCreateInfo->size; buffer->usage = pCreateInfo->usage; @@ -3525,15 +4136,16 @@ VkResult radv_CreateBuffer( buffer->flags = pCreateInfo->flags; buffer->shareable = vk_find_struct_const(pCreateInfo->pNext, - EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR) != NULL; + EXTERNAL_MEMORY_BUFFER_CREATE_INFO) != NULL; if (pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) { buffer->bo = device->ws->buffer_create(device->ws, align64(buffer->size, 4096), - 4096, 0, RADEON_FLAG_VIRTUAL); + 4096, 0, RADEON_FLAG_VIRTUAL, + RADV_BO_PRIORITY_VIRTUAL); if (!buffer->bo) { vk_free2(&device->alloc, pAllocator, buffer); - return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY); } } @@ -3559,13 +4171,22 @@ void radv_DestroyBuffer( vk_free2(&device->alloc, pAllocator, buffer); } +VkDeviceAddress radv_GetBufferDeviceAddressEXT( + VkDevice device, + const VkBufferDeviceAddressInfoEXT* pInfo) +{ + RADV_FROM_HANDLE(radv_buffer, buffer, pInfo->buffer); + return radv_buffer_get_va(buffer->bo) + buffer->offset; +} + + static inline unsigned -si_tile_mode_index(const struct radv_image *image, unsigned level, bool stencil) +si_tile_mode_index(const struct radv_image_plane *plane, unsigned level, bool stencil) { if (stencil) - return image->surface.u.legacy.stencil_tiling_index[level]; + return plane->surface.u.legacy.stencil_tiling_index[level]; else - return image->surface.u.legacy.tiling_index[level]; + return plane->surface.u.legacy.tiling_index[level]; } static uint32_t radv_surface_max_layer_count(struct radv_image_view *iview) @@ -3582,13 +4203,13 @@ radv_init_dcc_control_reg(struct radv_device *device, unsigned max_compressed_block_size; unsigned independent_64b_blocks; - if (device->physical_device->rad_info.chip_class < VI) + if (!radv_dcc_enabled(iview->image, iview->base_mip)) return 0; if (iview->image->info.samples > 1) { - if (iview->image->surface.bpe == 1) + if (iview->image->planes[0].surface.bpe == 1) max_uncompressed_block_size = V_028C78_MAX_BLOCK_SIZE_64B; - else if (iview->image->surface.bpe == 2) + else if (iview->image->planes[0].surface.bpe == 2) max_uncompressed_block_size = V_028C78_MAX_BLOCK_SIZE_128B; } @@ -3633,7 +4254,8 @@ radv_initialise_color_surface(struct radv_device *device, unsigned ntype, format, swap, endian; unsigned blend_clamp = 0, blend_bypass = 0; uint64_t va; - const struct radeon_surf *surf = &iview->image->surface; + const struct radv_image_plane *plane = &iview->image->planes[iview->plane_id]; + const struct radeon_surf *surf = &plane->surface; desc = vk_format_description(iview->vk_format); @@ -3642,35 +4264,37 @@ radv_initialise_color_surface(struct radv_device *device, /* Intensity is implemented as Red, so treat it that way. */ cb->cb_color_attrib = S_028C74_FORCE_DST_ALPHA_1(desc->swizzle[3] == VK_SWIZZLE_1); - va = radv_buffer_get_va(iview->bo) + iview->image->offset; + va = radv_buffer_get_va(iview->bo) + iview->image->offset + plane->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) - meta = iview->image->surface.u.gfx9.dcc; + meta = surf->u.gfx9.dcc; else - meta = iview->image->surface.u.gfx9.cmask; + meta = surf->u.gfx9.cmask; - cb->cb_color_attrib |= S_028C74_COLOR_SW_MODE(iview->image->surface.u.gfx9.surf.swizzle_mode) | - S_028C74_FMASK_SW_MODE(iview->image->surface.u.gfx9.fmask.swizzle_mode) | + cb->cb_color_attrib |= S_028C74_COLOR_SW_MODE(surf->u.gfx9.surf.swizzle_mode) | + S_028C74_FMASK_SW_MODE(surf->u.gfx9.fmask.swizzle_mode) | S_028C74_RB_ALIGNED(meta.rb_aligned) | S_028C74_PIPE_ALIGNED(meta.pipe_aligned); - cb->cb_color_base += iview->image->surface.u.gfx9.surf_offset >> 8; - cb->cb_color_base |= iview->image->surface.tile_swizzle; + cb->cb_color_base += surf->u.gfx9.surf_offset >> 8; + cb->cb_color_base |= surf->tile_swizzle; + + cb->cb_mrt_epitch = S_0287A0_EPITCH(surf->u.gfx9.surf.epitch); } 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; 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; + cb->cb_color_base |= surf->tile_swizzle; pitch_tile_max = level_info->nblk_x / 8 - 1; slice_tile_max = (level_info->nblk_x * level_info->nblk_y) / 64 - 1; - tile_mode_index = si_tile_mode_index(iview->image, iview->base_mip, false); + tile_mode_index = si_tile_mode_index(plane, iview->base_mip, false); cb->cb_color_pitch = S_028C64_TILE_MAX(pitch_tile_max); cb->cb_color_slice = S_028C68_TILE_MAX(slice_tile_max); @@ -3679,13 +4303,13 @@ radv_initialise_color_surface(struct radv_device *device, cb->cb_color_attrib |= S_028C74_TILE_MODE_INDEX(tile_mode_index); if (radv_image_has_fmask(iview->image)) { - if (device->physical_device->rad_info.chip_class >= CIK) + if (device->physical_device->rad_info.chip_class >= GFX7) cb->cb_color_pitch |= S_028C64_FMASK_TILE_MAX(iview->image->fmask.pitch_in_pixels / 8 - 1); cb->cb_color_attrib |= S_028C74_FMASK_TILE_MODE_INDEX(iview->image->fmask.tile_mode_index); cb->cb_color_fmask_slice = S_028C88_TILE_MAX(iview->image->fmask.slice_tile_max); } else { /* This must be set for fast clear to work without FMASK. */ - if (device->physical_device->rad_info.chip_class >= CIK) + if (device->physical_device->rad_info.chip_class >= GFX7) cb->cb_color_pitch |= S_028C64_FMASK_TILE_MAX(pitch_tile_max); cb->cb_color_attrib |= S_028C74_FMASK_TILE_MODE_INDEX(tile_mode_index); cb->cb_color_fmask_slice = S_028C88_TILE_MAX(slice_tile_max); @@ -3699,8 +4323,13 @@ radv_initialise_color_surface(struct radv_device *device, va = radv_buffer_get_va(iview->bo) + iview->image->offset; va += iview->image->dcc_offset; + + if (radv_dcc_enabled(iview->image, iview->base_mip) && + device->physical_device->rad_info.chip_class <= GFX8) + va += plane->surface.u.legacy.level[iview->base_mip].dcc_offset; + cb->cb_dcc_base = va >> 8; - cb->cb_dcc_base |= iview->image->surface.tile_swizzle; + cb->cb_dcc_base |= surf->tile_swizzle; uint32_t max_slice = radv_surface_max_layer_count(iview) - 1; cb->cb_color_view = S_028C6C_SLICE_START(iview->base_layer) | @@ -3765,10 +4394,24 @@ radv_initialise_color_surface(struct radv_device *device, S_028C70_ENDIAN(endian); if (radv_image_has_fmask(iview->image)) { cb->cb_color_info |= S_028C70_COMPRESSION(1); - if (device->physical_device->rad_info.chip_class == SI) { + if (device->physical_device->rad_info.chip_class == GFX6) { unsigned fmask_bankh = util_logbase2(iview->image->fmask.bank_height); cb->cb_color_attrib |= S_028C74_FMASK_BANK_HEIGHT(fmask_bankh); } + + if (radv_image_is_tc_compat_cmask(iview->image)) { + /* Allow the texture block to read FMASK directly + * without decompressing it. This bit must be cleared + * when performing FMASK_DECOMPRESS or DCC_COMPRESS, + * otherwise the operation doesn't happen. + */ + cb->cb_color_info |= S_028C70_FMASK_COMPRESS_1FRAG_ONLY(1); + + /* Set CMASK into a tiling format that allows the + * texture block to read it. + */ + cb->cb_color_info |= S_028C70_CMASK_ADDR_TYPE(2); + } } if (radv_image_has_cmask(iview->image) && @@ -3782,20 +4425,24 @@ radv_initialise_color_surface(struct radv_device *device, /* This must be set for fast clear to work without FMASK. */ if (!radv_image_has_fmask(iview->image) && - device->physical_device->rad_info.chip_class == SI) { - unsigned bankh = util_logbase2(iview->image->surface.u.legacy.bankh); + device->physical_device->rad_info.chip_class == GFX6) { + unsigned bankh = util_logbase2(surf->u.legacy.bankh); cb->cb_color_attrib |= S_028C74_FMASK_BANK_HEIGHT(bankh); } if (device->physical_device->rad_info.chip_class >= GFX9) { + const struct vk_format_description *format_desc = vk_format_description(iview->image->vk_format); + unsigned mip0_depth = iview->image->type == VK_IMAGE_TYPE_3D ? (iview->extent.depth - 1) : (iview->image->info.array_size - 1); + unsigned width = iview->extent.width / (iview->plane_id ? format_desc->width_divisor : 1); + unsigned height = iview->extent.height / (iview->plane_id ? format_desc->height_divisor : 1); 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->extent.width - 1) | - S_028C68_MIP0_HEIGHT(iview->extent.height - 1) | + S_028C74_RESOURCE_TYPE(surf->u.gfx9.resource_type); + cb->cb_color_attrib2 = S_028C68_MIP0_WIDTH(width - 1) | + S_028C68_MIP0_HEIGHT(height - 1) | S_028C68_MAX_MIP(iview->image->info.levels - 1); } } @@ -3848,6 +4495,11 @@ radv_initialise_ds_surface(struct radv_device *device, unsigned format, stencil_format; uint64_t va, s_offs, z_offs; bool stencil_only = false; + const struct radv_image_plane *plane = &iview->image->planes[0]; + const struct radeon_surf *surf = &plane->surface; + + assert(vk_format_get_plane_count(iview->image->vk_format) == 1); + memset(ds, 0, sizeof(*ds)); switch (iview->image->vk_format) { case VK_FORMAT_D24_UNORM_S8_UINT: @@ -3874,7 +4526,7 @@ radv_initialise_ds_surface(struct radv_device *device, } format = radv_translate_dbformat(iview->image->vk_format); - stencil_format = iview->image->surface.has_stencil ? + stencil_format = surf->has_stencil ? V_028044_STENCIL_8 : V_028044_STENCIL_INVALID; uint32_t max_slice = radv_surface_max_layer_count(iview) - 1; @@ -3888,18 +4540,19 @@ radv_initialise_ds_surface(struct radv_device *device, s_offs = z_offs = va; if (device->physical_device->rad_info.chip_class >= GFX9) { - assert(iview->image->surface.u.gfx9.surf_offset == 0); - s_offs += iview->image->surface.u.gfx9.stencil_offset; + assert(surf->u.gfx9.surf_offset == 0); + s_offs += surf->u.gfx9.stencil_offset; ds->db_z_info = S_028038_FORMAT(format) | S_028038_NUM_SAMPLES(util_logbase2(iview->image->info.samples)) | - S_028038_SW_MODE(iview->image->surface.u.gfx9.surf.swizzle_mode) | - S_028038_MAXMIP(iview->image->info.levels - 1); + S_028038_SW_MODE(surf->u.gfx9.surf.swizzle_mode) | + S_028038_MAXMIP(iview->image->info.levels - 1) | + S_028038_ZRANGE_PRECISION(1); ds->db_stencil_info = S_02803C_FORMAT(stencil_format) | - S_02803C_SW_MODE(iview->image->surface.u.gfx9.stencil.swizzle_mode); + S_02803C_SW_MODE(surf->u.gfx9.stencil.swizzle_mode); - ds->db_z_info2 = S_028068_EPITCH(iview->image->surface.u.gfx9.surf.epitch); - ds->db_stencil_info2 = S_02806C_EPITCH(iview->image->surface.u.gfx9.stencil.epitch); + ds->db_z_info2 = S_028068_EPITCH(surf->u.gfx9.surf.epitch); + ds->db_stencil_info2 = S_02806C_EPITCH(surf->u.gfx9.stencil.epitch); ds->db_depth_view |= S_028008_MIPID(level); ds->db_depth_size = S_02801C_X_MAX(iview->image->info.width - 1) | @@ -3917,24 +4570,24 @@ radv_initialise_ds_surface(struct radv_device *device, ds->db_stencil_info |= S_02803C_ITERATE_FLUSH(1); } - if (!iview->image->surface.has_stencil) + if (!surf->has_stencil) /* Use all of the htile_buffer for depth if there's no stencil. */ ds->db_stencil_info |= S_02803C_TILE_STENCIL_DISABLE(1); va = radv_buffer_get_va(iview->bo) + iview->image->offset + iview->image->htile_offset; ds->db_htile_data_base = va >> 8; ds->db_htile_surface = S_028ABC_FULL_CACHE(1) | - S_028ABC_PIPE_ALIGNED(iview->image->surface.u.gfx9.htile.pipe_aligned) | - S_028ABC_RB_ALIGNED(iview->image->surface.u.gfx9.htile.rb_aligned); + S_028ABC_PIPE_ALIGNED(surf->u.gfx9.htile.pipe_aligned) | + S_028ABC_RB_ALIGNED(surf->u.gfx9.htile.rb_aligned); } } else { - const struct legacy_surf_level *level_info = &iview->image->surface.u.legacy.level[level]; + const struct legacy_surf_level *level_info = &surf->u.legacy.level[level]; if (stencil_only) - level_info = &iview->image->surface.u.legacy.stencil_level[level]; + level_info = &surf->u.legacy.stencil_level[level]; - z_offs += iview->image->surface.u.legacy.level[level].offset; - s_offs += iview->image->surface.u.legacy.stencil_level[level].offset; + z_offs += surf->u.legacy.level[level].offset; + s_offs += surf->u.legacy.stencil_level[level].offset; ds->db_depth_info = S_02803C_ADDR5_SWIZZLE_MASK(!radv_image_is_tc_compat_htile(iview->image)); ds->db_z_info = S_028040_FORMAT(format) | S_028040_ZRANGE_PRECISION(1); @@ -3943,11 +4596,11 @@ radv_initialise_ds_surface(struct radv_device *device, if (iview->image->info.samples > 1) ds->db_z_info |= S_028040_NUM_SAMPLES(util_logbase2(iview->image->info.samples)); - if (device->physical_device->rad_info.chip_class >= CIK) { + if (device->physical_device->rad_info.chip_class >= GFX7) { struct radeon_info *info = &device->physical_device->rad_info; - unsigned tiling_index = iview->image->surface.u.legacy.tiling_index[level]; - unsigned stencil_index = iview->image->surface.u.legacy.stencil_tiling_index[level]; - unsigned macro_index = iview->image->surface.u.legacy.macro_tile_index; + unsigned tiling_index = surf->u.legacy.tiling_index[level]; + unsigned stencil_index = surf->u.legacy.stencil_tiling_index[level]; + unsigned macro_index = surf->u.legacy.macro_tile_index; unsigned tile_mode = info->si_tile_mode_array[tiling_index]; unsigned stencil_tile_mode = info->si_tile_mode_array[stencil_index]; unsigned macro_mode = info->cik_macrotile_mode_array[macro_index]; @@ -3965,9 +4618,9 @@ radv_initialise_ds_surface(struct radv_device *device, ds->db_z_info |= S_028040_TILE_SPLIT(G_009910_TILE_SPLIT(tile_mode)); ds->db_stencil_info |= S_028044_TILE_SPLIT(G_009910_TILE_SPLIT(stencil_tile_mode)); } else { - unsigned tile_mode_index = si_tile_mode_index(iview->image, level, false); + unsigned tile_mode_index = si_tile_mode_index(&iview->image->planes[0], level, false); ds->db_z_info |= S_028040_TILE_MODE_INDEX(tile_mode_index); - tile_mode_index = si_tile_mode_index(iview->image, level, true); + tile_mode_index = si_tile_mode_index(&iview->image->planes[0], 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); @@ -3980,7 +4633,7 @@ radv_initialise_ds_surface(struct radv_device *device, if (radv_htile_enabled(iview->image, level)) { ds->db_z_info |= S_028040_TILE_SURFACE_ENABLE(1); - if (!iview->image->surface.has_stencil && + if (!surf->has_stencil && !radv_image_is_tc_compat_htile(iview->image)) /* Use all of the htile_buffer for depth if there's no stencil. */ ds->db_stencil_info |= S_028044_TILE_STENCIL_DISABLE(1); @@ -4020,7 +4673,7 @@ VkResult radv_CreateFramebuffer( framebuffer = vk_alloc2(&device->alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (framebuffer == NULL) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); framebuffer->attachment_count = pCreateInfo->attachmentCount; framebuffer->width = pCreateInfo->width; @@ -4030,10 +4683,10 @@ VkResult radv_CreateFramebuffer( VkImageView _iview = pCreateInfo->pAttachments[i]; struct radv_image_view *iview = radv_image_view_from_handle(_iview); framebuffer->attachments[i].attachment = iview; - if (iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) { - radv_initialise_color_surface(device, &framebuffer->attachments[i].cb, iview); - } else if (iview->aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + if (iview->aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { radv_initialise_ds_surface(device, &framebuffer->attachments[i].ds, iview); + } else { + radv_initialise_color_surface(device, &framebuffer->attachments[i].cb, iview); } framebuffer->width = MIN2(framebuffer->width, iview->extent.width); framebuffer->height = MIN2(framebuffer->height, iview->extent.height); @@ -4170,27 +4823,40 @@ radv_tex_filter_mode(VkSamplerReductionModeEXT mode) { switch (mode) { case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT: - return SQ_IMG_FILTER_MODE_BLEND; + return V_008F30_SQ_IMG_FILTER_MODE_BLEND; case VK_SAMPLER_REDUCTION_MODE_MIN_EXT: - return SQ_IMG_FILTER_MODE_MIN; + return V_008F30_SQ_IMG_FILTER_MODE_MIN; case VK_SAMPLER_REDUCTION_MODE_MAX_EXT: - return SQ_IMG_FILTER_MODE_MAX; + return V_008F30_SQ_IMG_FILTER_MODE_MAX; default: break; } return 0; } +static uint32_t +radv_get_max_anisotropy(struct radv_device *device, + const VkSamplerCreateInfo *pCreateInfo) +{ + if (device->force_aniso >= 0) + return device->force_aniso; + + if (pCreateInfo->anisotropyEnable && + pCreateInfo->maxAnisotropy > 1.0f) + return (uint32_t)pCreateInfo->maxAnisotropy; + + return 0; +} + static void radv_init_sampler(struct radv_device *device, struct radv_sampler *sampler, const VkSamplerCreateInfo *pCreateInfo) { - uint32_t max_aniso = pCreateInfo->anisotropyEnable && pCreateInfo->maxAnisotropy > 1.0 ? - (uint32_t) pCreateInfo->maxAnisotropy : 0; + uint32_t max_aniso = radv_get_max_anisotropy(device, pCreateInfo); uint32_t max_aniso_ratio = radv_tex_aniso_filter(max_aniso); - bool is_vi = (device->physical_device->rad_info.chip_class >= VI); - unsigned filter_mode = SQ_IMG_FILTER_MODE_BLEND; + bool is_vi = (device->physical_device->rad_info.chip_class >= GFX8); + unsigned filter_mode = V_008F30_SQ_IMG_FILTER_MODE_BLEND; const struct VkSamplerReductionModeCreateInfoEXT *sampler_reduction = vk_find_struct_const(pCreateInfo->pNext, @@ -4217,7 +4883,7 @@ radv_init_sampler(struct radv_device *device, S_008F38_XY_MIN_FILTER(radv_tex_filter(pCreateInfo->minFilter, max_aniso)) | S_008F38_MIP_FILTER(radv_tex_mipfilter(pCreateInfo->mipmapMode)) | S_008F38_MIP_POINT_PRECLAMP(0) | - S_008F38_DISABLE_LSB_CEIL(device->physical_device->rad_info.chip_class <= VI) | + S_008F38_DISABLE_LSB_CEIL(device->physical_device->rad_info.chip_class <= GFX8) | S_008F38_FILTER_PREC_FIX(1) | S_008F38_ANISO_OVERRIDE(is_vi)); sampler->state[3] = (S_008F3C_BORDER_COLOR_PTR(0) | @@ -4233,14 +4899,20 @@ VkResult radv_CreateSampler( RADV_FROM_HANDLE(radv_device, device, _device); struct radv_sampler *sampler; + const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion = + vk_find_struct_const(pCreateInfo->pNext, + SAMPLER_YCBCR_CONVERSION_INFO); + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); sampler = vk_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!sampler) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); radv_init_sampler(device, sampler, pCreateInfo); + + sampler->ycbcr_sampler = ycbcr_conversion ? radv_sampler_ycbcr_conversion_from_handle(ycbcr_conversion->conversion): NULL; *pSampler = radv_sampler_to_handle(sampler); return VK_SUCCESS; @@ -4299,7 +4971,7 @@ vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion) * vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR, * because the loader no longer does so. */ - *pSupportedVersion = MIN2(*pSupportedVersion, 3u); + *pSupportedVersion = MIN2(*pSupportedVersion, 4u); return VK_SUCCESS; } @@ -4314,21 +4986,23 @@ VkResult radv_GetMemoryFdKHR(VkDevice _device, /* At the moment, we support only the below handle types. */ assert(pGetFdInfo->handleType == - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR || + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); bool ret = radv_get_memory_fd(device, memory, pFD); if (ret == false) - return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY); + return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY); return VK_SUCCESS; } VkResult radv_GetMemoryFdPropertiesKHR(VkDevice _device, - VkExternalMemoryHandleTypeFlagBitsKHR handleType, + VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR *pMemoryFdProperties) { + RADV_FROM_HANDLE(radv_device, device, _device); + switch (handleType) { case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: pMemoryFdProperties->memoryTypeBits = (1 << RADV_MEM_TYPE_COUNT) - 1; @@ -4342,7 +5016,7 @@ VkResult radv_GetMemoryFdPropertiesKHR(VkDevice _device, * * So opaque handle types fall into the default "unsupported" case. */ - return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR); + return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); } } @@ -4353,7 +5027,7 @@ static VkResult radv_import_opaque_fd(struct radv_device *device, 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); + return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); if (*syncobj) device->ws->destroy_syncobj(device->ws, *syncobj); @@ -4374,7 +5048,7 @@ static VkResult radv_import_sync_fd(struct radv_device *device, if (!syncobj_handle) { int ret = device->ws->create_syncobj(device->ws, &syncobj_handle); if (ret) { - return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR); + return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); } } @@ -4383,7 +5057,7 @@ static VkResult radv_import_sync_fd(struct radv_device *device, } 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); + return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); } *syncobj = syncobj_handle; @@ -4400,16 +5074,16 @@ VkResult radv_ImportSemaphoreFdKHR(VkDevice _device, RADV_FROM_HANDLE(radv_semaphore, sem, pImportSemaphoreFdInfo->semaphore); uint32_t *syncobj_dst = NULL; - if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR) { + if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) { syncobj_dst = &sem->temp_syncobj; } else { syncobj_dst = &sem->syncobj; } switch(pImportSemaphoreFdInfo->handleType) { - case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: return radv_import_opaque_fd(device, pImportSemaphoreFdInfo->fd, syncobj_dst); - case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR: + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: return radv_import_sync_fd(device, pImportSemaphoreFdInfo->fd, syncobj_dst); default: unreachable("Unhandled semaphore handle type"); @@ -4431,10 +5105,10 @@ VkResult radv_GetSemaphoreFdKHR(VkDevice _device, syncobj_handle = sem->syncobj; switch(pGetFdInfo->handleType) { - case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: ret = device->ws->export_syncobj(device->ws, syncobj_handle, pFd); break; - case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR: + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: ret = device->ws->export_syncobj_to_sync_file(device->ws, syncobj_handle, pFd); if (!ret) { if (sem->temp_syncobj) { @@ -4450,30 +5124,30 @@ VkResult radv_GetSemaphoreFdKHR(VkDevice _device, } if (ret) - return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR); + return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); return VK_SUCCESS; } void radv_GetPhysicalDeviceExternalSemaphoreProperties( VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo, - VkExternalSemaphorePropertiesKHR* pExternalSemaphoreProperties) + const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, + VkExternalSemaphoreProperties *pExternalSemaphoreProperties) { 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 | - VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR; + (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 | + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; + } else if (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) { + pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; + pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; + pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; } else { pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; pExternalSemaphoreProperties->compatibleHandleTypes = 0; @@ -4489,16 +5163,16 @@ VkResult radv_ImportFenceFdKHR(VkDevice _device, uint32_t *syncobj_dst = NULL; - if (pImportFenceFdInfo->flags & VK_FENCE_IMPORT_TEMPORARY_BIT_KHR) { + if (pImportFenceFdInfo->flags & VK_FENCE_IMPORT_TEMPORARY_BIT) { syncobj_dst = &fence->temp_syncobj; } else { syncobj_dst = &fence->syncobj; } switch(pImportFenceFdInfo->handleType) { - case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT: return radv_import_opaque_fd(device, pImportFenceFdInfo->fd, syncobj_dst); - case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR: + case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT: return radv_import_sync_fd(device, pImportFenceFdInfo->fd, syncobj_dst); default: unreachable("Unhandled fence handle type"); @@ -4520,10 +5194,10 @@ VkResult radv_GetFenceFdKHR(VkDevice _device, syncobj_handle = fence->syncobj; switch(pGetFdInfo->handleType) { - case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: + case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT: ret = device->ws->export_syncobj(device->ws, syncobj_handle, pFd); break; - case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR: + case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT: ret = device->ws->export_syncobj_to_sync_file(device->ws, syncobj_handle, pFd); if (!ret) { if (fence->temp_syncobj) { @@ -4539,24 +5213,24 @@ VkResult radv_GetFenceFdKHR(VkDevice _device, } if (ret) - return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR); + return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); return VK_SUCCESS; } void radv_GetPhysicalDeviceExternalFenceProperties( VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo, - VkExternalFencePropertiesKHR* pExternalFenceProperties) + 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_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; + (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 | + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; } else { pExternalFenceProperties->exportFromImportedHandleTypes = 0; pExternalFenceProperties->compatibleHandleTypes = 0; @@ -4616,3 +5290,136 @@ radv_GetDeviceGroupPeerMemoryFeatures( VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT | VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT; } + +static const VkTimeDomainEXT radv_time_domains[] = { + VK_TIME_DOMAIN_DEVICE_EXT, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT, + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT, +}; + +VkResult radv_GetPhysicalDeviceCalibrateableTimeDomainsEXT( + VkPhysicalDevice physicalDevice, + uint32_t *pTimeDomainCount, + VkTimeDomainEXT *pTimeDomains) +{ + int d; + VK_OUTARRAY_MAKE(out, pTimeDomains, pTimeDomainCount); + + for (d = 0; d < ARRAY_SIZE(radv_time_domains); d++) { + vk_outarray_append(&out, i) { + *i = radv_time_domains[d]; + } + } + + return vk_outarray_status(&out); +} + +static uint64_t +radv_clock_gettime(clockid_t clock_id) +{ + struct timespec current; + int ret; + + ret = clock_gettime(clock_id, ¤t); + if (ret < 0 && clock_id == CLOCK_MONOTONIC_RAW) + ret = clock_gettime(CLOCK_MONOTONIC, ¤t); + if (ret < 0) + return 0; + + return (uint64_t) current.tv_sec * 1000000000ULL + current.tv_nsec; +} + +VkResult radv_GetCalibratedTimestampsEXT( + VkDevice _device, + uint32_t timestampCount, + const VkCalibratedTimestampInfoEXT *pTimestampInfos, + uint64_t *pTimestamps, + uint64_t *pMaxDeviation) +{ + RADV_FROM_HANDLE(radv_device, device, _device); + uint32_t clock_crystal_freq = device->physical_device->rad_info.clock_crystal_freq; + int d; + uint64_t begin, end; + uint64_t max_clock_period = 0; + + begin = radv_clock_gettime(CLOCK_MONOTONIC_RAW); + + for (d = 0; d < timestampCount; d++) { + switch (pTimestampInfos[d].timeDomain) { + case VK_TIME_DOMAIN_DEVICE_EXT: + pTimestamps[d] = device->ws->query_value(device->ws, + RADEON_TIMESTAMP); + uint64_t device_period = DIV_ROUND_UP(1000000, clock_crystal_freq); + max_clock_period = MAX2(max_clock_period, device_period); + break; + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT: + pTimestamps[d] = radv_clock_gettime(CLOCK_MONOTONIC); + max_clock_period = MAX2(max_clock_period, 1); + break; + + case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT: + pTimestamps[d] = begin; + break; + default: + pTimestamps[d] = 0; + break; + } + } + + end = radv_clock_gettime(CLOCK_MONOTONIC_RAW); + + /* + * The maximum deviation is the sum of the interval over which we + * perform the sampling and the maximum period of any sampled + * clock. That's because the maximum skew between any two sampled + * clock edges is when the sampled clock with the largest period is + * sampled at the end of that period but right at the beginning of the + * sampling interval and some other clock is sampled right at the + * begining of its sampling period and right at the end of the + * sampling interval. Let's assume the GPU has the longest clock + * period and that the application is sampling GPU and monotonic: + * + * s e + * w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e f + * Raw -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- + * + * g + * 0 1 2 3 + * GPU -----_____-----_____-----_____-----_____ + * + * m + * x y z 0 1 2 3 4 5 6 7 8 9 a b c + * Monotonic -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- + * + * Interval <-----------------> + * Deviation <--------------------------> + * + * s = read(raw) 2 + * g = read(GPU) 1 + * m = read(monotonic) 2 + * e = read(raw) b + * + * We round the sample interval up by one tick to cover sampling error + * in the interval clock + */ + + uint64_t sample_interval = end - begin + 1; + + *pMaxDeviation = sample_interval + max_clock_period; + + return VK_SUCCESS; +} + +void radv_GetPhysicalDeviceMultisamplePropertiesEXT( + VkPhysicalDevice physicalDevice, + VkSampleCountFlagBits samples, + VkMultisamplePropertiesEXT* pMultisampleProperties) +{ + if (samples & (VK_SAMPLE_COUNT_2_BIT | + VK_SAMPLE_COUNT_4_BIT | + VK_SAMPLE_COUNT_8_BIT)) { + pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 2, 2 }; + } else { + pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 0, 0 }; + } +}