X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Famd%2Fvulkan%2Fradv_device.c;h=5fdb894146cb1d3347248765ea20c7ccaba391dd;hp=ae54ac563d6ca08e4593ff9913c1df7ca1722141;hb=dc6182fa3fea0de025f29591b9fd053fffe8bf8b;hpb=93e62898ccb752cf8e2040044f6a3700e7d1c812 diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index ae54ac563d6..5fdb894146c 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -33,7 +33,7 @@ #include "radv_cs.h" #include "util/disk_cache.h" #include "util/strtod.h" -#include "util/vk_util.h" +#include "vk_util.h" #include #include #include @@ -42,6 +42,7 @@ #include "ac_llvm_util.h" #include "vk_format.h" #include "sid.h" +#include "gfx9d.h" #include "util/debug.h" static int @@ -61,6 +62,15 @@ radv_device_get_cache_uuid(enum radeon_family family, void *uuid) return 0; } +static void +radv_get_device_uuid(drmDevicePtr device, void *uuid) { + memset(uuid, 0, VK_UUID_SIZE); + memcpy((char*)uuid + 0, &device->businfo.pci->domain, 2); + memcpy((char*)uuid + 2, &device->businfo.pci->bus, 1); + memcpy((char*)uuid + 3, &device->businfo.pci->dev, 1); + memcpy((char*)uuid + 4, &device->businfo.pci->func, 1); +} + static const VkExtensionProperties instance_extensions[] = { { .extensionName = VK_KHR_SURFACE_EXTENSION_NAME, @@ -84,13 +94,33 @@ static const VkExtensionProperties instance_extensions[] = { .specVersion = 5, }, #endif + { + .extensionName = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, + .specVersion = 1, + }, + { + .extensionName = VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, + .specVersion = 1, + }, }; static const VkExtensionProperties common_device_extensions[] = { + { + .extensionName = VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, + .specVersion = 1, + }, + { + .extensionName = VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, + .specVersion = 1, + }, { .extensionName = VK_KHR_MAINTENANCE1_EXTENSION_NAME, .specVersion = 1, }, + { + .extensionName = VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, + .specVersion = 1, + }, { .extensionName = VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, .specVersion = 1, @@ -104,15 +134,19 @@ static const VkExtensionProperties common_device_extensions[] = { .specVersion = 1, }, { - .extensionName = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, + .extensionName = VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, .specVersion = 1, }, { - .extensionName = VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, + .extensionName = VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME, .specVersion = 1, }, { - .extensionName = VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME, + .extensionName = VK_KHX_EXTERNAL_MEMORY_EXTENSION_NAME, + .specVersion = 1, + }, + { + .extensionName = VK_KHX_EXTERNAL_MEMORY_FD_EXTENSION_NAME, .specVersion = 1, }, }; @@ -175,11 +209,40 @@ is_extension_enabled(const VkExtensionProperties *extensions, return false; } +static const char * +get_chip_name(enum radeon_family family) +{ + switch (family) { + case CHIP_TAHITI: return "AMD RADV TAHITI"; + case CHIP_PITCAIRN: return "AMD RADV PITCAIRN"; + case CHIP_VERDE: return "AMD RADV CAPE VERDE"; + case CHIP_OLAND: return "AMD RADV OLAND"; + case CHIP_HAINAN: return "AMD RADV HAINAN"; + case CHIP_BONAIRE: return "AMD RADV BONAIRE"; + case CHIP_KAVERI: return "AMD RADV KAVERI"; + case CHIP_KABINI: return "AMD RADV KABINI"; + case CHIP_HAWAII: return "AMD RADV HAWAII"; + case CHIP_MULLINS: return "AMD RADV MULLINS"; + case CHIP_TONGA: return "AMD RADV TONGA"; + case CHIP_ICELAND: return "AMD RADV ICELAND"; + case CHIP_CARRIZO: return "AMD RADV CARRIZO"; + case CHIP_FIJI: return "AMD RADV FIJI"; + case CHIP_POLARIS10: return "AMD RADV POLARIS10"; + case CHIP_POLARIS11: return "AMD RADV POLARIS11"; + case CHIP_POLARIS12: return "AMD RADV POLARIS12"; + case CHIP_STONEY: return "AMD RADV STONEY"; + case CHIP_VEGA10: return "AMD RADV VEGA"; + case CHIP_RAVEN: return "AMD RADV RAVEN"; + default: return "AMD RADV unknown"; + } +} + static VkResult radv_physical_device_init(struct radv_physical_device *device, struct radv_instance *instance, - const char *path) + drmDevicePtr drm_device) { + const char *path = drm_device->nodes[DRM_NODE_RENDER]; VkResult result; drmVersionPtr version; int fd; @@ -237,7 +300,15 @@ radv_physical_device_init(struct radv_physical_device *device, goto fail; fprintf(stderr, "WARNING: radv is not a conformant vulkan implementation, testing use only.\n"); - device->name = device->rad_info.name; + device->name = get_chip_name(device->rad_info.family); + + radv_get_device_uuid(drm_device, device->device_uuid); + + if (device->rad_info.family == CHIP_STONEY || + device->rad_info.chip_class >= GFX9) { + device->has_rbplus = true; + device->rbplus_allowed = device->rad_info.family == CHIP_STONEY; + } return VK_SUCCESS; @@ -255,7 +326,6 @@ radv_physical_device_finish(struct radv_physical_device *device) close(device->local_fd); } - static void * default_alloc_func(void *pUserData, size_t size, size_t align, VkSystemAllocationScope allocationScope) @@ -389,7 +459,7 @@ radv_enumerate_devices(struct radv_instance *instance) instance->physicalDeviceCount = 0; - max_devices = drmGetDevices2(0, devices, sizeof(devices)); + max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); if (max_devices < 1) return VK_ERROR_INCOMPATIBLE_DRIVER; @@ -401,13 +471,15 @@ radv_enumerate_devices(struct radv_instance *instance) result = radv_physical_device_init(instance->physicalDevices + instance->physicalDeviceCount, instance, - devices[i]->nodes[DRM_NODE_RENDER]); + devices[i]); if (result == VK_SUCCESS) ++instance->physicalDeviceCount; else if (result != VK_ERROR_INCOMPATIBLE_DRIVER) - return result; + break; } } + drmFreeDevices(devices, max_devices); + return result; } @@ -442,8 +514,8 @@ void radv_GetPhysicalDeviceFeatures( VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) { - // RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); - + RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); + bool is_gfx9 = pdevice->rad_info.chip_class >= GFX9; memset(pFeatures, 0, sizeof(*pFeatures)); *pFeatures = (VkPhysicalDeviceFeatures) { @@ -451,8 +523,8 @@ void radv_GetPhysicalDeviceFeatures( .fullDrawIndexUint32 = true, .imageCubeArray = true, .independentBlend = true, - .geometryShader = true, - .tessellationShader = false, + .geometryShader = !is_gfx9, + .tessellationShader = !is_gfx9, .sampleRateShading = false, .dualSrcBlend = true, .logicOp = true, @@ -471,7 +543,7 @@ void radv_GetPhysicalDeviceFeatures( .textureCompressionASTC_LDR = false, .textureCompressionBC = true, .occlusionQueryPrecise = true, - .pipelineStatisticsQuery = false, + .pipelineStatisticsQuery = true, .vertexPipelineStoresAndAtomics = true, .fragmentStoresAndAtomics = true, .shaderTessellationAndGeometryPointSize = true, @@ -489,8 +561,9 @@ void radv_GetPhysicalDeviceFeatures( .shaderFloat64 = true, .shaderInt64 = false, .shaderInt16 = false, - .variableMultisampleRate = false, - .inheritedQueries = false, + .sparseBinding = true, + .variableMultisampleRate = true, + .inheritedQueries = true, }; } @@ -501,34 +574,26 @@ void radv_GetPhysicalDeviceFeatures2KHR( return radv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features); } -static uint32_t radv_get_driver_version() -{ - const char *minor_string = strchr(VERSION, '.'); - const char *patch_string = minor_string ? strchr(minor_string + 1, ','): NULL; - int major = atoi(VERSION); - int minor = minor_string ? atoi(minor_string + 1) : 0; - int patch = patch_string ? atoi(patch_string + 1) : 0; - if (strstr(VERSION, "devel")) { - if (patch == 0) { - patch = 99; - if (minor == 0) { - minor = 99; - --major; - } else - --minor; - } else - --patch; - } - uint32_t version = VK_MAKE_VERSION(major, minor, patch); - return version; -} - void radv_GetPhysicalDeviceProperties( VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) { RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); VkSampleCountFlags sample_counts = 0xf; + + /* make sure that the entire descriptor set is addressable with a signed + * 32-bit int. So the sum of all limits scaled by descriptor size has to + * be at most 2 GiB. the combined image & samples object count as one of + * both. This limit is for the pipeline layout, not for the set layout, but + * there is no set limit, so we just set a pipeline limit. I don't think + * any app is going to hit this soon. */ + size_t max_descriptor_set_size = ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS) / + (32 /* uniform buffer, 32 due to potential space wasted on alignement */ + + 32 /* storage buffer, 32 due to potential space wasted on alignement */ + + 32 /* sampler, largest when combined with image */ + + 64 /* sampled image */ + + 64 /* storage image */); + VkPhysicalDeviceLimits limits = { .maxImageDimension1D = (1 << 14), .maxImageDimension2D = (1 << 14), @@ -542,37 +607,37 @@ void radv_GetPhysicalDeviceProperties( .maxMemoryAllocationCount = UINT32_MAX, .maxSamplerAllocationCount = 64 * 1024, .bufferImageGranularity = 64, /* A cache line */ - .sparseAddressSpaceSize = 0, + .sparseAddressSpaceSize = 0xffffffffu, /* buffer max size */ .maxBoundDescriptorSets = MAX_SETS, - .maxPerStageDescriptorSamplers = 64, - .maxPerStageDescriptorUniformBuffers = 64, - .maxPerStageDescriptorStorageBuffers = 64, - .maxPerStageDescriptorSampledImages = 64, - .maxPerStageDescriptorStorageImages = 64, - .maxPerStageDescriptorInputAttachments = 64, - .maxPerStageResources = 128, - .maxDescriptorSetSamplers = 256, - .maxDescriptorSetUniformBuffers = 256, - .maxDescriptorSetUniformBuffersDynamic = 256, - .maxDescriptorSetStorageBuffers = 256, - .maxDescriptorSetStorageBuffersDynamic = 256, - .maxDescriptorSetSampledImages = 256, - .maxDescriptorSetStorageImages = 256, - .maxDescriptorSetInputAttachments = 256, + .maxPerStageDescriptorSamplers = max_descriptor_set_size, + .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size, + .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size, + .maxPerStageDescriptorSampledImages = max_descriptor_set_size, + .maxPerStageDescriptorStorageImages = max_descriptor_set_size, + .maxPerStageDescriptorInputAttachments = max_descriptor_set_size, + .maxPerStageResources = max_descriptor_set_size, + .maxDescriptorSetSamplers = max_descriptor_set_size, + .maxDescriptorSetUniformBuffers = max_descriptor_set_size, + .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2, + .maxDescriptorSetStorageBuffers = max_descriptor_set_size, + .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2, + .maxDescriptorSetSampledImages = max_descriptor_set_size, + .maxDescriptorSetStorageImages = max_descriptor_set_size, + .maxDescriptorSetInputAttachments = max_descriptor_set_size, .maxVertexInputAttributes = 32, .maxVertexInputBindings = 32, .maxVertexInputAttributeOffset = 2047, .maxVertexInputBindingStride = 2048, .maxVertexOutputComponents = 128, - .maxTessellationGenerationLevel = 0, - .maxTessellationPatchSize = 0, - .maxTessellationControlPerVertexInputComponents = 0, - .maxTessellationControlPerVertexOutputComponents = 0, - .maxTessellationControlPerPatchOutputComponents = 0, - .maxTessellationControlTotalOutputComponents = 0, - .maxTessellationEvaluationInputComponents = 0, - .maxTessellationEvaluationOutputComponents = 0, - .maxGeometryShaderInvocations = 32, + .maxTessellationGenerationLevel = 64, + .maxTessellationPatchSize = 32, + .maxTessellationControlPerVertexInputComponents = 128, + .maxTessellationControlPerVertexOutputComponents = 128, + .maxTessellationControlPerPatchOutputComponents = 120, + .maxTessellationControlTotalOutputComponents = 4096, + .maxTessellationEvaluationInputComponents = 128, + .maxTessellationEvaluationOutputComponents = 128, + .maxGeometryShaderInvocations = 127, .maxGeometryInputComponents = 64, .maxGeometryOutputComponents = 128, .maxGeometryOutputVertices = 256, @@ -625,8 +690,8 @@ void radv_GetPhysicalDeviceProperties( .sampledImageStencilSampleCounts = sample_counts, .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT, .maxSampleMaskWords = 1, - .timestampComputeAndGraphics = false, - .timestampPeriod = 100000.0 / pdevice->rad_info.clock_crystal_freq, + .timestampComputeAndGraphics = true, + .timestampPeriod = 1000000.0 / pdevice->rad_info.clock_crystal_freq, .maxClipDistances = 8, .maxCullDistances = 8, .maxCombinedClipAndCullDistances = 8, @@ -644,12 +709,12 @@ void radv_GetPhysicalDeviceProperties( *pProperties = (VkPhysicalDeviceProperties) { .apiVersion = VK_MAKE_VERSION(1, 0, 42), - .driverVersion = radv_get_driver_version(), + .driverVersion = vk_get_driver_version(), .vendorID = 0x1002, .deviceID = pdevice->rad_info.pci_id, - .deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, + .deviceType = pdevice->rad_info.has_dedicated_vram ? VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU : VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, .limits = limits, - .sparseProperties = {0}, /* Broadwell doesn't do sparse. */ + .sparseProperties = {0}, }; strcpy(pProperties->deviceName, pdevice->name); @@ -660,7 +725,28 @@ void radv_GetPhysicalDeviceProperties2KHR( VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2KHR *pProperties) { - return radv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties); + RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice); + radv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties); + + vk_foreach_struct(ext, pProperties->pNext) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: { + VkPhysicalDevicePushDescriptorPropertiesKHR *properties = + (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext; + properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX: { + VkPhysicalDeviceIDPropertiesKHX *properties = (VkPhysicalDeviceIDPropertiesKHX*)ext; + radv_device_get_cache_uuid(0, properties->driverUUID); + memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE); + properties->deviceLUIDValid = false; + break; + } + default: + break; + } + } } static void radv_get_physical_device_queue_family_properties( @@ -670,7 +756,7 @@ static void radv_get_physical_device_queue_family_properties( { int num_queue_families = 1; int idx; - if (pdevice->rad_info.compute_rings > 0 && + if (pdevice->rad_info.num_compute_rings > 0 && pdevice->rad_info.chip_class >= CIK && !(pdevice->instance->debug_flags & RADV_DEBUG_NO_COMPUTE_QUEUE)) num_queue_families++; @@ -687,8 +773,9 @@ static void radv_get_physical_device_queue_family_properties( if (*pCount >= 1) { *pQueueFamilyProperties[idx] = (VkQueueFamilyProperties) { .queueFlags = VK_QUEUE_GRAPHICS_BIT | - VK_QUEUE_COMPUTE_BIT | - VK_QUEUE_TRANSFER_BIT, + VK_QUEUE_COMPUTE_BIT | + VK_QUEUE_TRANSFER_BIT | + VK_QUEUE_SPARSE_BINDING_BIT, .queueCount = 1, .timestampValidBits = 64, .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 }, @@ -696,13 +783,15 @@ static void radv_get_physical_device_queue_family_properties( idx++; } - if (pdevice->rad_info.compute_rings > 0 && + if (pdevice->rad_info.num_compute_rings > 0 && pdevice->rad_info.chip_class >= CIK && !(pdevice->instance->debug_flags & RADV_DEBUG_NO_COMPUTE_QUEUE)) { if (*pCount > idx) { *pQueueFamilyProperties[idx] = (VkQueueFamilyProperties) { - .queueFlags = VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, - .queueCount = pdevice->rad_info.compute_rings, + .queueFlags = VK_QUEUE_COMPUTE_BIT | + VK_QUEUE_TRANSFER_BIT | + VK_QUEUE_SPARSE_BINDING_BIT, + .queueCount = pdevice->rad_info.num_compute_rings, .timestampValidBits = 64, .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 }, }; @@ -786,11 +875,11 @@ void radv_GetPhysicalDeviceMemoryProperties( pMemoryProperties->memoryHeapCount = RADV_MEM_HEAP_COUNT; pMemoryProperties->memoryHeaps[RADV_MEM_HEAP_VRAM] = (VkMemoryHeap) { .size = physical_device->rad_info.vram_size - - physical_device->rad_info.visible_vram_size, + physical_device->rad_info.vram_vis_size, .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, }; pMemoryProperties->memoryHeaps[RADV_MEM_HEAP_VRAM_CPU_ACCESS] = (VkMemoryHeap) { - .size = physical_device->rad_info.visible_vram_size, + .size = physical_device->rad_info.vram_vis_size, .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, }; pMemoryProperties->memoryHeaps[RADV_MEM_HEAP_GTT] = (VkMemoryHeap) { @@ -841,6 +930,10 @@ radv_queue_finish(struct radv_queue *queue) queue->device->ws->buffer_destroy(queue->esgs_ring_bo); if (queue->gsvs_ring_bo) queue->device->ws->buffer_destroy(queue->gsvs_ring_bo); + if (queue->tess_factor_ring_bo) + queue->device->ws->buffer_destroy(queue->tess_factor_ring_bo); + if (queue->tess_offchip_ring_bo) + queue->device->ws->buffer_destroy(queue->tess_offchip_ring_bo); if (queue->compute_scratch_bo) queue->device->ws->buffer_destroy(queue->compute_scratch_bo); } @@ -868,6 +961,9 @@ radv_device_init_gs_info(struct radv_device *device) case CHIP_FIJI: case CHIP_POLARIS10: case CHIP_POLARIS11: + case CHIP_POLARIS12: + case CHIP_VEGA10: + case CHIP_RAVEN: device->gs_table_depth = 32; return; default: @@ -958,6 +1054,12 @@ VkResult radv_CreateDevice( radv_device_init_gs_info(device); + 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.max_se >= 2; + result = radv_device_init_meta(device); if (result != VK_SUCCESS) goto fail; @@ -985,6 +1087,7 @@ VkResult radv_CreateDevice( case RADV_QUEUE_COMPUTE: si_cs_emit_cache_flush(device->flush_cs[family], device->physical_device->rad_info.chip_class, + NULL, 0, family == RADV_QUEUE_COMPUTE && device->physical_device->rad_info.chip_class >= CIK, RADV_CMD_FLAG_INV_ICACHE | RADV_CMD_FLAG_INV_SMEM_L1 | @@ -993,6 +1096,23 @@ VkResult radv_CreateDevice( break; } device->ws->cs_finalize(device->flush_cs[family]); + + device->flush_shader_cs[family] = device->ws->cs_create(device->ws, family); + switch (family) { + case RADV_QUEUE_GENERAL: + case RADV_QUEUE_COMPUTE: + si_cs_emit_cache_flush(device->flush_shader_cs[family], + device->physical_device->rad_info.chip_class, + NULL, 0, + family == RADV_QUEUE_COMPUTE && device->physical_device->rad_info.chip_class >= CIK, + family == 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); + break; + } + device->ws->cs_finalize(device->flush_shader_cs[family]); } if (getenv("RADV_TRACE_FILE")) { @@ -1068,6 +1188,8 @@ void radv_DestroyDevice( device->ws->cs_destroy(device->empty_cs[i]); if (device->flush_cs[i]) device->ws->cs_destroy(device->flush_cs[i]); + if (device->flush_shader_cs[i]) + device->ws->cs_destroy(device->flush_shader_cs[i]); } radv_device_finish_meta(device); @@ -1172,20 +1294,30 @@ static void radv_dump_trace(struct radv_device *device, } static void -fill_geom_rings(struct radv_queue *queue, - uint32_t *map, - uint32_t esgs_ring_size, - struct radeon_winsys_bo *esgs_ring_bo, - uint32_t gsvs_ring_size, - struct radeon_winsys_bo *gsvs_ring_bo) +fill_geom_tess_rings(struct radv_queue *queue, + uint32_t *map, + bool add_sample_positions, + uint32_t esgs_ring_size, + struct radeon_winsys_bo *esgs_ring_bo, + uint32_t gsvs_ring_size, + struct radeon_winsys_bo *gsvs_ring_bo, + uint32_t tess_factor_ring_size, + struct radeon_winsys_bo *tess_factor_ring_bo, + uint32_t tess_offchip_ring_size, + struct radeon_winsys_bo *tess_offchip_ring_bo) { uint64_t esgs_va = 0, gsvs_va = 0; + uint64_t tess_factor_va = 0, tess_offchip_va = 0; uint32_t *desc = &map[4]; if (esgs_ring_bo) esgs_va = queue->device->ws->buffer_get_va(esgs_ring_bo); if (gsvs_ring_bo) gsvs_va = queue->device->ws->buffer_get_va(gsvs_ring_bo); + if (tess_factor_ring_bo) + tess_factor_va = queue->device->ws->buffer_get_va(tess_factor_ring_bo); + if (tess_offchip_ring_bo) + tess_offchip_va = queue->device->ws->buffer_get_va(tess_offchip_ring_bo); /* stride 0, num records - size, add tid, swizzle, elsize4, index stride 64 */ @@ -1260,6 +1392,99 @@ fill_geom_rings(struct radv_queue *queue, S_008F0C_ELEMENT_SIZE(1) | S_008F0C_INDEX_STRIDE(1) | S_008F0C_ADD_TID_ENABLE(true); + desc += 4; + + desc[0] = tess_factor_va; + desc[1] = S_008F04_BASE_ADDRESS_HI(tess_factor_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); + desc += 8; + memcpy(desc, queue->device->sample_locations_8x, 64); + desc += 16; + memcpy(desc, queue->device->sample_locations_16x, 128); +} + +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 && + 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 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: + offchip_granularity = V_03093C_X_4K_DWORDS; + break; + } + + switch (device->physical_device->rad_info.chip_class) { + case SI: + max_offchip_buffers = MIN2(max_offchip_buffers, 126); + break; + case CIK: + case VI: + case GFX9: + default: + max_offchip_buffers = MIN2(max_offchip_buffers, 508); + break; + } + + *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) + --max_offchip_buffers; + hs_offchip_param = + S_03093C_OFFCHIP_BUFFERING(max_offchip_buffers) | + S_03093C_OFFCHIP_GRANULARITY(offchip_granularity); + } else { + hs_offchip_param = + S_0089B0_OFFCHIP_BUFFERING(max_offchip_buffers); + } + return hs_offchip_param; } static VkResult @@ -1268,6 +1493,8 @@ radv_get_preamble_cs(struct radv_queue *queue, uint32_t compute_scratch_size, uint32_t esgs_ring_size, uint32_t gsvs_ring_size, + bool needs_tess_rings, + bool needs_sample_positions, struct radeon_winsys_cs **initial_preamble_cs, struct radeon_winsys_cs **continue_preamble_cs) { @@ -1276,12 +1503,32 @@ radv_get_preamble_cs(struct radv_queue *queue, struct radeon_winsys_bo *compute_scratch_bo = NULL; struct radeon_winsys_bo *esgs_ring_bo = NULL; struct radeon_winsys_bo *gsvs_ring_bo = NULL; + struct radeon_winsys_bo *tess_factor_ring_bo = NULL; + struct radeon_winsys_bo *tess_offchip_ring_bo = NULL; struct radeon_winsys_cs *dest_cs[2] = {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; + unsigned hs_offchip_param = 0; + if (!queue->has_tess_rings) { + if (needs_tess_rings) + add_tess_rings = true; + } + if (!queue->has_sample_positions) { + if (needs_sample_positions) + add_sample_positions = true; + } + tess_factor_ring_size = 32768 * queue->device->physical_device->rad_info.max_se; + hs_offchip_param = radv_get_hs_offchip_param(queue->device, + &max_offchip_buffers); + tess_offchip_ring_size = max_offchip_buffers * + queue->device->tess_offchip_block_dw_size * 4; if (scratch_size <= queue->scratch_size && compute_scratch_size <= queue->compute_scratch_size && esgs_ring_size <= queue->esgs_ring_size && gsvs_ring_size <= queue->gsvs_ring_size && + !add_tess_rings && !add_sample_positions && queue->initial_preamble_cs) { *initial_preamble_cs = queue->initial_preamble_cs; *continue_preamble_cs = queue->continue_preamble_cs; @@ -1339,12 +1586,38 @@ radv_get_preamble_cs(struct radv_queue *queue, gsvs_ring_size = queue->gsvs_ring_size; } + if (add_tess_rings) { + tess_factor_ring_bo = queue->device->ws->buffer_create(queue->device->ws, + tess_factor_ring_size, + 256, + RADEON_DOMAIN_VRAM, + RADEON_FLAG_NO_CPU_ACCESS); + if (!tess_factor_ring_bo) + goto fail; + tess_offchip_ring_bo = queue->device->ws->buffer_create(queue->device->ws, + tess_offchip_ring_size, + 256, + RADEON_DOMAIN_VRAM, + RADEON_FLAG_NO_CPU_ACCESS); + if (!tess_offchip_ring_bo) + goto fail; + } else { + tess_factor_ring_bo = queue->tess_factor_ring_bo; + tess_offchip_ring_bo = queue->tess_offchip_ring_bo; + } + if (scratch_bo != queue->scratch_bo || esgs_ring_bo != queue->esgs_ring_bo || - gsvs_ring_bo != queue->gsvs_ring_bo) { + gsvs_ring_bo != queue->gsvs_ring_bo || + tess_factor_ring_bo != queue->tess_factor_ring_bo || + tess_offchip_ring_bo != queue->tess_offchip_ring_bo || add_sample_positions) { uint32_t size = 0; - if (gsvs_ring_bo || esgs_ring_bo) - size = 80; /* 2 dword + 2 padding + 4 dword * 4 */ + if (gsvs_ring_bo || esgs_ring_bo || + tess_factor_ring_bo || tess_offchip_ring_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. */ + } else if (scratch_bo) size = 8; /* 2 dword */ @@ -1376,6 +1649,12 @@ radv_get_preamble_cs(struct radv_queue *queue, if (gsvs_ring_bo) queue->device->ws->cs_add_buffer(cs, gsvs_ring_bo, 8); + if (tess_factor_ring_bo) + queue->device->ws->cs_add_buffer(cs, tess_factor_ring_bo, 8); + + if (tess_offchip_ring_bo) + queue->device->ws->cs_add_buffer(cs, tess_offchip_ring_bo, 8); + if (descriptor_bo) queue->device->ws->cs_add_buffer(cs, descriptor_bo, 8); @@ -1390,18 +1669,25 @@ radv_get_preamble_cs(struct radv_queue *queue, map[1] = rsrc1; } - if (esgs_ring_bo || gsvs_ring_bo) - fill_geom_rings(queue, map, esgs_ring_size, esgs_ring_bo, gsvs_ring_size, gsvs_ring_bo); + if (esgs_ring_bo || gsvs_ring_bo || tess_factor_ring_bo || tess_offchip_ring_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_factor_ring_bo, + tess_offchip_ring_size, tess_offchip_ring_bo); queue->device->ws->buffer_unmap(descriptor_bo); } - if (esgs_ring_bo || gsvs_ring_bo) { + if (esgs_ring_bo || gsvs_ring_bo || tess_factor_ring_bo || tess_offchip_ring_bo) { radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); radeon_emit(cs, EVENT_TYPE(V_028A90_VS_PARTIAL_FLUSH) | EVENT_INDEX(4)); radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0)); 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); @@ -1413,6 +1699,28 @@ radv_get_preamble_cs(struct radv_queue *queue, } } + if (tess_factor_ring_bo) { + uint64_t tf_va = queue->device->ws->buffer_get_va(tess_factor_ring_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, + 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) { uint32_t regs[] = {R_00B030_SPI_SHADER_USER_DATA_PS_0, R_00B130_SPI_SHADER_USER_DATA_VS_0, @@ -1445,6 +1753,7 @@ radv_get_preamble_cs(struct radv_queue *queue, if (!i) { 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, RADV_CMD_FLAG_INV_ICACHE | @@ -1494,6 +1803,15 @@ radv_get_preamble_cs(struct radv_queue *queue, queue->gsvs_ring_size = gsvs_ring_size; } + if (tess_factor_ring_bo != queue->tess_factor_ring_bo) { + queue->tess_factor_ring_bo = tess_factor_ring_bo; + } + + if (tess_offchip_ring_bo != queue->tess_offchip_ring_bo) { + queue->tess_offchip_ring_bo = tess_offchip_ring_bo; + queue->has_tess_rings = true; + } + if (descriptor_bo != queue->descriptor_bo) { if (queue->descriptor_bo) queue->device->ws->buffer_destroy(queue->descriptor_bo); @@ -1501,6 +1819,9 @@ radv_get_preamble_cs(struct radv_queue *queue, queue->descriptor_bo = descriptor_bo; } + if (add_sample_positions) + queue->has_sample_positions = true; + *initial_preamble_cs = queue->initial_preamble_cs; *continue_preamble_cs = queue->continue_preamble_cs; if (!scratch_size && !compute_scratch_size && !esgs_ring_size && !gsvs_ring_size) @@ -1520,6 +1841,10 @@ fail: queue->device->ws->buffer_destroy(esgs_ring_bo); if (gsvs_ring_bo && gsvs_ring_bo != queue->gsvs_ring_bo) queue->device->ws->buffer_destroy(gsvs_ring_bo); + if (tess_factor_ring_bo && tess_factor_ring_bo != queue->tess_factor_ring_bo) + queue->device->ws->buffer_destroy(tess_factor_ring_bo); + if (tess_offchip_ring_bo && tess_offchip_ring_bo != queue->tess_offchip_ring_bo) + queue->device->ws->buffer_destroy(tess_offchip_ring_bo); return VK_ERROR_OUT_OF_DEVICE_MEMORY; } @@ -1541,6 +1866,8 @@ VkResult radv_QueueSubmit( struct radeon_winsys_cs *initial_preamble_cs = NULL, *continue_preamble_cs = NULL; VkResult result; bool fence_emitted = false; + bool tess_rings_needed = false; + bool sample_positions_needed = false; /* Do this first so failing to allocate scratch buffers can't result in * partially executed submissions. */ @@ -1554,18 +1881,21 @@ VkResult radv_QueueSubmit( cmd_buffer->compute_scratch_size_needed); esgs_ring_size = MAX2(esgs_ring_size, cmd_buffer->esgs_ring_size_needed); gsvs_ring_size = MAX2(gsvs_ring_size, cmd_buffer->gsvs_ring_size_needed); + tess_rings_needed |= cmd_buffer->tess_rings_needed; + sample_positions_needed |= cmd_buffer->sample_positions_needed; } } result = radv_get_preamble_cs(queue, scratch_size, compute_scratch_size, - esgs_ring_size, gsvs_ring_size, + esgs_ring_size, gsvs_ring_size, tess_rings_needed, + sample_positions_needed, &initial_preamble_cs, &continue_preamble_cs); if (result != VK_SUCCESS) return result; for (uint32_t i = 0; i < submitCount; i++) { struct radeon_winsys_cs **cs_array; - bool do_flush = !i; + bool do_flush = !i || pSubmits[i].pWaitDstStageMask; bool can_patch = !do_flush; uint32_t advance; @@ -1592,7 +1922,9 @@ VkResult radv_QueueSubmit( (pSubmits[i].commandBufferCount + do_flush)); if(do_flush) - cs_array[0] = queue->device->flush_cs[queue->queue_family_index]; + cs_array[0] = pSubmits[i].waitSemaphoreCount ? + queue->device->flush_shader_cs[queue->queue_family_index] : + queue->device->flush_cs[queue->queue_family_index]; for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) { RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, @@ -1735,7 +2067,7 @@ VkResult radv_AllocateMemory( VkResult result; enum radeon_bo_domain domain; uint32_t flags = 0; - const VkDedicatedAllocationMemoryAllocateInfoNV *dedicate_info = NULL; + assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); if (pAllocateInfo->allocationSize == 0) { @@ -1744,15 +2076,10 @@ VkResult radv_AllocateMemory( return VK_SUCCESS; } - vk_foreach_struct(ext, pAllocateInfo->pNext) { - switch (ext->sType) { - case VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV: - dedicate_info = (const VkDedicatedAllocationMemoryAllocateInfoNV *)ext; - break; - default: - break; - } - } + const VkImportMemoryFdInfoKHX *import_info = + vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHX); + const VkDedicatedAllocationMemoryAllocateInfoNV *dedicate_info = + vk_find_struct_const(pAllocateInfo->pNext, DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV); mem = vk_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); @@ -1767,6 +2094,17 @@ VkResult radv_AllocateMemory( mem->buffer = NULL; } + if (import_info) { + assert(import_info->handleType == + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX); + mem->bo = device->ws->buffer_from_fd(device->ws, import_info->fd, + NULL, NULL); + if (!mem->bo) + goto fail; + else + goto out_success; + } + uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096); if (pAllocateInfo->memoryTypeIndex == RADV_MEM_TYPE_GTT_WRITE_COMBINE || pAllocateInfo->memoryTypeIndex == RADV_MEM_TYPE_GTT_CACHED) @@ -1790,7 +2128,7 @@ VkResult radv_AllocateMemory( goto fail; } mem->type_index = pAllocateInfo->memoryTypeIndex; - +out_success: *pMem = radv_device_memory_to_handle(mem); return VK_SUCCESS; @@ -1881,8 +2219,12 @@ void radv_GetBufferMemoryRequirements( pMemoryRequirements->memoryTypeBits = (1u << RADV_MEM_TYPE_COUNT) - 1; - pMemoryRequirements->size = buffer->size; - pMemoryRequirements->alignment = 16; + if (buffer->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) + pMemoryRequirements->alignment = 4096; + else + pMemoryRequirements->alignment = 16; + + pMemoryRequirements->size = align64(buffer->size, pMemoryRequirements->alignment); } void radv_GetImageMemoryRequirements( @@ -1955,13 +2297,89 @@ VkResult radv_BindImageMemory( return VK_SUCCESS; } -VkResult radv_QueueBindSparse( - VkQueue queue, + +static void +radv_sparse_buffer_bind_memory(struct radv_device *device, + const VkSparseBufferMemoryBindInfo *bind) +{ + RADV_FROM_HANDLE(radv_buffer, buffer, bind->buffer); + + for (uint32_t i = 0; i < bind->bindCount; ++i) { + struct radv_device_memory *mem = NULL; + + if (bind->pBinds[i].memory != VK_NULL_HANDLE) + mem = radv_device_memory_from_handle(bind->pBinds[i].memory); + + device->ws->buffer_virtual_bind(buffer->bo, + bind->pBinds[i].resourceOffset, + bind->pBinds[i].size, + mem ? mem->bo : NULL, + bind->pBinds[i].memoryOffset); + } +} + +static void +radv_sparse_image_opaque_bind_memory(struct radv_device *device, + const VkSparseImageOpaqueMemoryBindInfo *bind) +{ + RADV_FROM_HANDLE(radv_image, image, bind->image); + + for (uint32_t i = 0; i < bind->bindCount; ++i) { + struct radv_device_memory *mem = NULL; + + if (bind->pBinds[i].memory != VK_NULL_HANDLE) + mem = radv_device_memory_from_handle(bind->pBinds[i].memory); + + device->ws->buffer_virtual_bind(image->bo, + bind->pBinds[i].resourceOffset, + bind->pBinds[i].size, + mem ? mem->bo : NULL, + bind->pBinds[i].memoryOffset); + } +} + + VkResult radv_QueueBindSparse( + VkQueue _queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, - VkFence fence) + VkFence _fence) { - stub_return(VK_ERROR_INCOMPATIBLE_DRIVER); + RADV_FROM_HANDLE(radv_fence, fence, _fence); + RADV_FROM_HANDLE(radv_queue, queue, _queue); + struct radeon_winsys_fence *base_fence = fence ? fence->fence : NULL; + bool fence_emitted = false; + + for (uint32_t i = 0; i < bindInfoCount; ++i) { + for (uint32_t j = 0; j < pBindInfo[i].bufferBindCount; ++j) { + radv_sparse_buffer_bind_memory(queue->device, + pBindInfo[i].pBufferBinds + j); + } + + for (uint32_t j = 0; j < pBindInfo[i].imageOpaqueBindCount; ++j) { + radv_sparse_image_opaque_bind_memory(queue->device, + pBindInfo[i].pImageOpaqueBinds + j); + } + + if (pBindInfo[i].waitSemaphoreCount || pBindInfo[i].signalSemaphoreCount) { + queue->device->ws->cs_submit(queue->hw_ctx, queue->queue_idx, + &queue->device->empty_cs[queue->queue_family_index], + 1, NULL, NULL, + (struct radeon_winsys_sem **)pBindInfo[i].pWaitSemaphores, + pBindInfo[i].waitSemaphoreCount, + (struct radeon_winsys_sem **)pBindInfo[i].pSignalSemaphores, + pBindInfo[i].signalSemaphoreCount, + false, base_fence); + fence_emitted = true; + if (fence) + fence->submitted = true; + } + } + + if (fence && !fence_emitted) { + fence->signalled = true; + } + + return VK_SUCCESS; } VkResult radv_CreateFence( @@ -2208,6 +2626,17 @@ VkResult radv_CreateBuffer( buffer->usage = pCreateInfo->usage; buffer->bo = NULL; buffer->offset = 0; + buffer->flags = pCreateInfo->flags; + + 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); + if (!buffer->bo) { + vk_free2(&device->alloc, pAllocator, buffer); + return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY); + } + } *pBuffer = radv_buffer_to_handle(buffer); @@ -2225,6 +2654,9 @@ void radv_DestroyBuffer( if (!buffer) return; + if (buffer->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) + device->ws->buffer_destroy(buffer->bo); + vk_free2(&device->alloc, pAllocator, buffer); } @@ -2232,9 +2664,9 @@ static inline unsigned si_tile_mode_index(const struct radv_image *image, unsigned level, bool stencil) { if (stencil) - return image->surface.stencil_tiling_index[level]; + return image->surface.u.legacy.stencil_tiling_index[level]; else - return image->surface.tiling_index[level]; + return image->surface.u.legacy.tiling_index[level]; } static uint32_t radv_surface_layer_count(struct radv_image_view *iview) @@ -2250,24 +2682,68 @@ radv_initialise_color_surface(struct radv_device *device, const struct vk_format_description *desc; unsigned ntype, format, swap, endian; unsigned blend_clamp = 0, blend_bypass = 0; - unsigned pitch_tile_max, slice_tile_max, tile_mode_index; uint64_t va; const struct radeon_surf *surf = &iview->image->surface; - const struct radeon_surf_level *level_info = &surf->level[iview->base_mip]; desc = vk_format_description(iview->vk_format); memset(cb, 0, sizeof(*cb)); + /* 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 = device->ws->buffer_get_va(iview->bo) + iview->image->offset; - va += level_info->offset; + + 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; + else + meta = iview->image->surface.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) | + S_028C74_RB_ALIGNED(meta.rb_aligned) | + S_028C74_PIPE_ALIGNED(meta.pipe_aligned); + + va += iview->image->surface.u.gfx9.surf_offset >> 8; + } else { + const struct legacy_surf_level *level_info = &surf->u.legacy.level[iview->base_mip]; + unsigned pitch_tile_max, slice_tile_max, tile_mode_index; + + va += level_info->offset; + + 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); + + cb->cb_color_pitch = S_028C64_TILE_MAX(pitch_tile_max); + cb->cb_color_slice = S_028C68_TILE_MAX(slice_tile_max); + cb->cb_color_cmask_slice = iview->image->cmask.slice_tile_max; + + cb->cb_color_attrib |= S_028C74_TILE_MODE_INDEX(tile_mode_index); + cb->micro_tile_mode = iview->image->surface.micro_tile_mode; + + if (iview->image->fmask.size) { + if (device->physical_device->rad_info.chip_class >= CIK) + 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) + 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); + } + } + cb->cb_color_base = va >> 8; /* CMASK variables */ va = device->ws->buffer_get_va(iview->bo) + iview->image->offset; va += iview->image->cmask.offset; cb->cb_color_cmask = va >> 8; - cb->cb_color_cmask_slice = iview->image->cmask.slice_tile_max; va = device->ws->buffer_get_va(iview->bo) + iview->image->offset; va += iview->image->dcc_offset; @@ -2277,20 +2753,8 @@ radv_initialise_color_surface(struct radv_device *device, cb->cb_color_view = S_028C6C_SLICE_START(iview->base_layer) | S_028C6C_SLICE_MAX(iview->base_layer + max_slice - 1); - cb->micro_tile_mode = iview->image->surface.micro_tile_mode; - 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); - - cb->cb_color_pitch = S_028C64_TILE_MAX(pitch_tile_max); - cb->cb_color_slice = S_028C68_TILE_MAX(slice_tile_max); - - /* 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) | - S_028C74_TILE_MODE_INDEX(tile_mode_index); - - if (iview->image->samples > 1) { - unsigned log_samples = util_logbase2(iview->image->samples); + if (iview->image->info.samples > 1) { + unsigned log_samples = util_logbase2(iview->image->info.samples); cb->cb_color_attrib |= S_028C74_NUM_SAMPLES(log_samples) | S_028C74_NUM_FRAGMENTS(log_samples); @@ -2298,18 +2762,9 @@ radv_initialise_color_surface(struct radv_device *device, if (iview->image->fmask.size) { va = device->ws->buffer_get_va(iview->bo) + iview->image->offset + iview->image->fmask.offset; - if (device->physical_device->rad_info.chip_class >= CIK) - 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 = va >> 8; - 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) - 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 = cb->cb_color_base; - cb->cb_color_fmask_slice = S_028C88_TILE_MAX(slice_tile_max); } ntype = radv_translate_color_numformat(iview->vk_format, @@ -2354,7 +2809,7 @@ radv_initialise_color_surface(struct radv_device *device, format != V_028C70_COLOR_24_8) | S_028C70_NUMBER_TYPE(ntype) | S_028C70_ENDIAN(endian); - if (iview->image->samples > 1) + if (iview->image->info.samples > 1) if (iview->image->fmask.size) cb->cb_color_info |= S_028C70_COMPRESSION(1); @@ -2362,12 +2817,12 @@ radv_initialise_color_surface(struct radv_device *device, !(device->debug_flags & RADV_DEBUG_NO_FAST_CLEARS)) cb->cb_color_info |= S_028C70_FAST_CLEAR(1); - if (iview->image->surface.dcc_size && level_info->dcc_enabled) + if (iview->image->surface.dcc_size && iview->base_mip < surf->num_dcc_levels) cb->cb_color_info |= S_028C70_DCC_ENABLE(1); if (device->physical_device->rad_info.chip_class >= VI) { unsigned max_uncompressed_block_size = 2; - if (iview->image->samples > 1) { + if (iview->image->info.samples > 1) { if (iview->image->surface.bpe == 1) max_uncompressed_block_size = 0; else if (iview->image->surface.bpe == 2) @@ -2381,9 +2836,24 @@ radv_initialise_color_surface(struct radv_device *device, /* This must be set for fast clear to work without FMASK. */ if (!iview->image->fmask.size && device->physical_device->rad_info.chip_class == SI) { - unsigned bankh = util_logbase2(iview->image->surface.bankh); + unsigned bankh = util_logbase2(iview->image->surface.u.legacy.bankh); cb->cb_color_attrib |= S_028C74_FMASK_BANK_HEIGHT(bankh); } + + if (device->physical_device->rad_info.chip_class >= GFX9) { + uint32_t max_slice = radv_surface_layer_count(iview); + unsigned mip0_depth = iview->base_layer + max_slice - 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->image->info.width - 1) | + S_028C68_MIP0_HEIGHT(iview->image->info.height - 1) | + S_028C68_MAX_MIP(iview->image->info.levels); + + cb->gfx9_epitch = S_0287A0_EPITCH(iview->image->surface.u.gfx9.surf.epitch); + + } } static void @@ -2392,9 +2862,9 @@ radv_initialise_ds_surface(struct radv_device *device, struct radv_image_view *iview) { unsigned level = iview->base_mip; - unsigned format; + unsigned format, stencil_format; uint64_t va, s_offs, z_offs; - const struct radeon_surf_level *level_info = &iview->image->surface.level[level]; + bool stencil_only = false; memset(ds, 0, sizeof(*ds)); switch (iview->vk_format) { case VK_FORMAT_D24_UNORM_S8_UINT: @@ -2413,93 +2883,123 @@ radv_initialise_ds_surface(struct radv_device *device, S_028B78_POLY_OFFSET_DB_IS_FLOAT_FMT(1); ds->offset_scale = 1.0f; break; + case VK_FORMAT_S8_UINT: + stencil_only = true; + break; default: break; } format = radv_translate_dbformat(iview->vk_format); - - va = device->ws->buffer_get_va(iview->bo) + iview->image->offset; - s_offs = z_offs = va; - z_offs += iview->image->surface.level[level].offset; - s_offs += iview->image->surface.stencil_level[level].offset; + stencil_format = iview->image->surface.flags & RADEON_SURF_SBUFFER ? + V_028044_STENCIL_8 : V_028044_STENCIL_INVALID; uint32_t max_slice = radv_surface_layer_count(iview); ds->db_depth_view = S_028008_SLICE_START(iview->base_layer) | S_028008_SLICE_MAX(iview->base_layer + max_slice - 1); - ds->db_depth_info = S_02803C_ADDR5_SWIZZLE_MASK(1); - ds->db_z_info = S_028040_FORMAT(format) | S_028040_ZRANGE_PRECISION(1); - if (iview->image->samples > 1) - ds->db_z_info |= S_028040_NUM_SAMPLES(util_logbase2(iview->image->samples)); + ds->db_htile_data_base = 0; + ds->db_htile_surface = 0; - if (iview->image->surface.flags & RADEON_SURF_SBUFFER) - ds->db_stencil_info = S_028044_FORMAT(V_028044_STENCIL_8); - else - ds->db_stencil_info = S_028044_FORMAT(V_028044_STENCIL_INVALID); + va = device->ws->buffer_get_va(iview->bo) + iview->image->offset; + s_offs = z_offs = va; - if (device->physical_device->rad_info.chip_class >= CIK) { - struct radeon_info *info = &device->physical_device->rad_info; - unsigned tiling_index = iview->image->surface.tiling_index[level]; - unsigned stencil_index = iview->image->surface.stencil_tiling_index[level]; - unsigned macro_index = iview->image->surface.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]; - - ds->db_depth_info |= - S_02803C_ARRAY_MODE(G_009910_ARRAY_MODE(tile_mode)) | - S_02803C_PIPE_CONFIG(G_009910_PIPE_CONFIG(tile_mode)) | - S_02803C_BANK_WIDTH(G_009990_BANK_WIDTH(macro_mode)) | - S_02803C_BANK_HEIGHT(G_009990_BANK_HEIGHT(macro_mode)) | - S_02803C_MACRO_TILE_ASPECT(G_009990_MACRO_TILE_ASPECT(macro_mode)) | - S_02803C_NUM_BANKS(G_009990_NUM_BANKS(macro_mode)); - 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); - ds->db_z_info |= S_028040_TILE_MODE_INDEX(tile_mode_index); - tile_mode_index = si_tile_mode_index(iview->image, level, true); - ds->db_stencil_info |= S_028044_TILE_MODE_INDEX(tile_mode_index); - } - - if (iview->image->surface.htile_size && !level) { - ds->db_z_info |= S_028040_TILE_SURFACE_ENABLE(1) | - S_028040_ALLOW_EXPCLEAR(1); - - if (iview->image->surface.flags & RADEON_SURF_SBUFFER) { - /* Workaround: For a not yet understood reason, the - * combination of MSAA, fast stencil clear and stencil - * decompress messes with subsequent stencil buffer - * uses. Problem was reproduced on Verde, Bonaire, - * Tonga, and Carrizo. - * - * Disabling EXPCLEAR works around the problem. - * - * Check piglit's arb_texture_multisample-stencil-clear - * test if you want to try changing this. - */ - if (iview->image->samples <= 1) - ds->db_stencil_info |= S_028044_ALLOW_EXPCLEAR(1); - } else - /* Use all of the htile_buffer for depth if there's no stencil. */ - ds->db_stencil_info |= S_028044_TILE_STENCIL_DISABLE(1); - - va = device->ws->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); + 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; + + 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); + ds->db_stencil_info = S_02803C_FORMAT(stencil_format) | + S_02803C_SW_MODE(iview->image->surface.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_depth_view |= S_028008_MIPID(level); + + ds->db_depth_size = S_02801C_X_MAX(iview->image->info.width - 1) | + S_02801C_Y_MAX(iview->image->info.height - 1); + + /* Only use HTILE for the first level. */ + if (iview->image->surface.htile_size && !level) { + ds->db_z_info |= S_028038_TILE_SURFACE_ENABLE(1); + + if (!(iview->image->surface.flags & RADEON_SURF_SBUFFER)) + /* Use all of the htile_buffer for depth if there's no stencil. */ + ds->db_stencil_info |= S_02803C_TILE_STENCIL_DISABLE(1); + va = device->ws->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); + } } else { - ds->db_htile_data_base = 0; - ds->db_htile_surface = 0; + const struct legacy_surf_level *level_info = &iview->image->surface.u.legacy.level[level]; + + if (stencil_only) + level_info = &iview->image->surface.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; + + ds->db_depth_info = S_02803C_ADDR5_SWIZZLE_MASK(1); + ds->db_z_info = S_028040_FORMAT(format) | S_028040_ZRANGE_PRECISION(1); + ds->db_stencil_info = S_028044_FORMAT(stencil_format); + + 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) { + 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 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]; + + if (stencil_only) + tile_mode = stencil_tile_mode; + + ds->db_depth_info |= + S_02803C_ARRAY_MODE(G_009910_ARRAY_MODE(tile_mode)) | + S_02803C_PIPE_CONFIG(G_009910_PIPE_CONFIG(tile_mode)) | + S_02803C_BANK_WIDTH(G_009990_BANK_WIDTH(macro_mode)) | + S_02803C_BANK_HEIGHT(G_009990_BANK_HEIGHT(macro_mode)) | + S_02803C_MACRO_TILE_ASPECT(G_009990_MACRO_TILE_ASPECT(macro_mode)) | + S_02803C_NUM_BANKS(G_009990_NUM_BANKS(macro_mode)); + 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); + ds->db_z_info |= S_028040_TILE_MODE_INDEX(tile_mode_index); + tile_mode_index = si_tile_mode_index(iview->image, level, true); + ds->db_stencil_info |= S_028044_TILE_MODE_INDEX(tile_mode_index); + } + + ds->db_depth_size = S_028058_PITCH_TILE_MAX((level_info->nblk_x / 8) - 1) | + S_028058_HEIGHT_TILE_MAX((level_info->nblk_y / 8) - 1); + ds->db_depth_slice = S_02805C_SLICE_TILE_MAX((level_info->nblk_x * level_info->nblk_y) / 64 - 1); + + if (iview->image->surface.htile_size && !level) { + ds->db_z_info |= S_028040_TILE_SURFACE_ENABLE(1); + + if (!(iview->image->surface.flags & RADEON_SURF_SBUFFER)) + /* Use all of the htile_buffer for depth if there's no stencil. */ + ds->db_stencil_info |= S_028044_TILE_STENCIL_DISABLE(1); + + va = device->ws->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); + } } ds->db_z_read_base = ds->db_z_write_base = z_offs >> 8; ds->db_stencil_read_base = ds->db_stencil_write_base = s_offs >> 8; - - ds->db_depth_size = S_028058_PITCH_TILE_MAX((level_info->nblk_x / 8) - 1) | - S_028058_HEIGHT_TILE_MAX((level_info->nblk_y / 8) - 1); - ds->db_depth_slice = S_02805C_SLICE_TILE_MAX((level_info->nblk_x * level_info->nblk_y) / 64 - 1); } VkResult radv_CreateFramebuffer( @@ -2733,7 +3233,6 @@ void radv_DestroySampler( vk_free2(&device->alloc, pAllocator, sampler); } - /* vk_icd.h does not declare this function, so we declare it here to * suppress Wmissing-prototypes. */ @@ -2777,3 +3276,34 @@ vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion) *pSupportedVersion = MIN2(*pSupportedVersion, 3u); return VK_SUCCESS; } + +VkResult radv_GetMemoryFdKHX(VkDevice _device, + VkDeviceMemory _memory, + VkExternalMemoryHandleTypeFlagsKHX handleType, + int *pFD) +{ + RADV_FROM_HANDLE(radv_device, device, _device); + RADV_FROM_HANDLE(radv_device_memory, memory, _memory); + + /* We support only one handle type. */ + assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX); + + bool ret = radv_get_memory_fd(device, memory, pFD); + if (ret == false) + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + return VK_SUCCESS; +} + +VkResult radv_GetMemoryFdPropertiesKHX(VkDevice _device, + VkExternalMemoryHandleTypeFlagBitsKHX handleType, + int fd, + VkMemoryFdPropertiesKHX *pMemoryFdProperties) +{ + /* The valid usage section for this function says: + * + * "handleType must not be one of the handle types defined as opaque." + * + * Since we only handle opaque handles for now, there are no FD properties. + */ + return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX; +}