From 57e796a12a883f5845c8e0ed05ec6bdb6d055b53 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Tue, 7 Apr 2020 06:11:24 +0100 Subject: [PATCH] radv: Implement VK_EXT_custom_border_color Reviewed-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Part-of: --- docs/relnotes/new_features.txt | 1 + src/amd/vulkan/radv_device.c | 133 +++++++++++++++++++++++++++++++++++++- src/amd/vulkan/radv_extensions.py | 1 + src/amd/vulkan/radv_private.h | 17 +++++ src/amd/vulkan/si_cmd_buffer.c | 10 +++ 5 files changed, 160 insertions(+), 2 deletions(-) diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index 857b888..3562f5c 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -1,2 +1,3 @@ GL_ARB_compute_variable_group_size on Iris. VK_EXT_private_data on ANV and RADV. +VK_EXT_custom_border_color on RADV. diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index bdfb2da..b4b429a 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -1294,6 +1294,12 @@ void radv_GetPhysicalDeviceFeatures2( features->robustBufferAccess2 = true; features->robustImageAccess2 = true; features->nullDescriptor = true; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: { + VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = + (VkPhysicalDeviceCustomBorderColorFeaturesEXT *)ext; + features->customBorderColors = true; + features->customBorderColorWithoutFormat = true; break; } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: { @@ -1938,6 +1944,11 @@ void radv_GetPhysicalDeviceProperties2( (VkPhysicalDeviceRobustness2PropertiesEXT *)ext; properties->robustStorageBufferAccessSizeAlignment = 4; properties->robustUniformBufferAccessSizeAlignment = 4; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: { + VkPhysicalDeviceCustomBorderColorPropertiesEXT *props = + (VkPhysicalDeviceCustomBorderColorPropertiesEXT *)ext; + props->maxCustomBorderColorSamplers = RADV_BORDER_COLOR_COUNT; break; } default: @@ -2936,6 +2947,37 @@ check_physical_device_features(VkPhysicalDevice physicalDevice, return VK_SUCCESS; } +static VkResult radv_device_init_border_color(struct radv_device *device) +{ + device->border_color_data.bo = + device->ws->buffer_create(device->ws, + RADV_BORDER_COLOR_BUFFER_SIZE, + 4096, + RADEON_DOMAIN_VRAM, + RADEON_FLAG_CPU_ACCESS | + RADEON_FLAG_READ_ONLY | + RADEON_FLAG_NO_INTERPROCESS_SHARING, + RADV_BO_PRIORITY_SHADER); + + if (device->border_color_data.bo == NULL) + return vk_error(device->physical_device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY); + + device->border_color_data.colors_gpu_ptr = + device->ws->buffer_map(device->border_color_data.bo); + pthread_mutex_init(&device->border_color_data.mutex, NULL); + + return VK_SUCCESS; +} + +static void radv_device_finish_border_color(struct radv_device *device) +{ + if (device->border_color_data.bo) { + device->ws->buffer_destroy(device->border_color_data.bo); + + pthread_mutex_destroy(&device->border_color_data.mutex); + } +} + VkResult radv_CreateDevice( VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, @@ -2949,6 +2991,7 @@ VkResult radv_CreateDevice( bool keep_shader_info = false; bool robust_buffer_access = false; bool overallocation_disallowed = false; + bool custom_border_colors = false; /* Check enabled features */ if (pCreateInfo->pEnabledFeatures) { @@ -2980,6 +3023,11 @@ VkResult radv_CreateDevice( overallocation_disallowed = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: { + const VkPhysicalDeviceCustomBorderColorFeaturesEXT *border_color_features = (const void *)ext; + custom_border_colors = border_color_features->customBorderColors; + break; + } default: break; } @@ -3150,6 +3198,13 @@ VkResult radv_CreateDevice( radv_device_init_msaa(device); + /* If the border color extension is enabled, let's create the buffer we need. */ + if (custom_border_colors) { + result = radv_device_init_border_color(device); + if (result != VK_SUCCESS) + goto fail; + } + for (int family = 0; family < RADV_MAX_QUEUE_FAMILIES; ++family) { device->empty_cs[family] = device->ws->cs_create(device->ws, family); switch (family) { @@ -3221,6 +3276,8 @@ fail: if (device->gfx_init) device->ws->buffer_destroy(device->gfx_init); + radv_device_finish_border_color(device); + for (unsigned i = 0; i < RADV_MAX_QUEUE_FAMILIES; i++) { for (unsigned q = 0; q < device->queue_count[i]; q++) radv_queue_finish(&device->queues[i][q]); @@ -3247,6 +3304,8 @@ void radv_DestroyDevice( if (device->gfx_init) device->ws->buffer_destroy(device->gfx_init); + radv_device_finish_border_color(device); + for (unsigned i = 0; i < RADV_MAX_QUEUE_FAMILIES; i++) { for (unsigned q = 0; q < device->queue_count[i]; q++) radv_queue_finish(&device->queues[i][q]); @@ -7094,6 +7153,9 @@ radv_tex_bordercolor(VkBorderColor bcolor) case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: case VK_BORDER_COLOR_INT_OPAQUE_WHITE: return V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE; + case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: + case VK_BORDER_COLOR_INT_CUSTOM_EXT: + return V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER; default: break; } @@ -7149,6 +7211,40 @@ static inline int S_FIXED(float value, unsigned frac_bits) return value * (1 << frac_bits); } +static uint32_t radv_register_border_color(struct radv_device *device, + VkClearColorValue value) +{ + uint32_t slot; + + pthread_mutex_lock(&device->border_color_data.mutex); + + for (slot = 0; slot < RADV_BORDER_COLOR_COUNT; slot++) { + if (!device->border_color_data.used[slot]) { + /* Copy to the GPU wrt endian-ness. */ + util_memcpy_cpu_to_le32(&device->border_color_data.colors_gpu_ptr[slot], + &value, + sizeof(VkClearColorValue)); + + device->border_color_data.used[slot] = true; + break; + } + } + + pthread_mutex_unlock(&device->border_color_data.mutex); + + return slot; +} + +static void radv_unregister_border_color(struct radv_device *device, + uint32_t slot) +{ + pthread_mutex_lock(&device->border_color_data.mutex); + + device->border_color_data.used[slot] = false; + + pthread_mutex_unlock(&device->border_color_data.mutex); +} + static void radv_init_sampler(struct radv_device *device, struct radv_sampler *sampler, @@ -7161,6 +7257,11 @@ radv_init_sampler(struct radv_device *device, unsigned filter_mode = V_008F30_SQ_IMG_FILTER_MODE_BLEND; unsigned depth_compare_func = V_008F30_SQ_TEX_DEPTH_COMPARE_NEVER; bool trunc_coord = pCreateInfo->minFilter == VK_FILTER_NEAREST && pCreateInfo->magFilter == VK_FILTER_NEAREST; + bool uses_border_color = pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER || + pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER || + pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + VkBorderColor border_color = uses_border_color ? pCreateInfo->borderColor : VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + uint32_t border_color_ptr; const struct VkSamplerReductionModeCreateInfo *sampler_reduction = vk_find_struct_const(pCreateInfo->pNext, @@ -7171,6 +7272,30 @@ radv_init_sampler(struct radv_device *device, if (pCreateInfo->compareEnable) depth_compare_func = radv_tex_compare(pCreateInfo->compareOp); + sampler->border_color_slot = RADV_BORDER_COLOR_COUNT; + + if (border_color == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT || border_color == VK_BORDER_COLOR_INT_CUSTOM_EXT) { + const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color = + vk_find_struct_const(pCreateInfo->pNext, + SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT); + + assert(custom_border_color); + + sampler->border_color_slot = + radv_register_border_color(device, custom_border_color->customBorderColor); + + /* Did we fail to find a slot? */ + if (sampler->border_color_slot == RADV_BORDER_COLOR_COUNT) { + fprintf(stderr, "WARNING: no free border color slots, defaulting to TRANS_BLACK.\n"); + border_color = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + } + } + + /* If we don't have a custom color, set the ptr to 0 */ + border_color_ptr = sampler->border_color_slot != RADV_BORDER_COLOR_COUNT + ? sampler->border_color_slot + : 0; + sampler->state[0] = (S_008F30_CLAMP_X(radv_tex_wrap(pCreateInfo->addressModeU)) | S_008F30_CLAMP_Y(radv_tex_wrap(pCreateInfo->addressModeV)) | S_008F30_CLAMP_Z(radv_tex_wrap(pCreateInfo->addressModeW)) | @@ -7191,8 +7316,8 @@ 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)); - sampler->state[3] = (S_008F3C_BORDER_COLOR_PTR(0) | - S_008F3C_BORDER_COLOR_TYPE(radv_tex_bordercolor(pCreateInfo->borderColor))); + sampler->state[3] = (S_008F3C_BORDER_COLOR_PTR(border_color_ptr) | + S_008F3C_BORDER_COLOR_TYPE(radv_tex_bordercolor(border_color))); if (device->physical_device->rad_info.chip_class >= GFX10) { sampler->state[2] |= S_008F38_ANISO_OVERRIDE_GFX10(1); @@ -7245,6 +7370,10 @@ void radv_DestroySampler( if (!sampler) return; + + if (sampler->border_color_slot != RADV_BORDER_COLOR_COUNT) + radv_unregister_border_color(device, sampler->border_color_slot); + vk_object_base_finish(&sampler->base); vk_free2(&device->vk.alloc, pAllocator, sampler); } diff --git a/src/amd/vulkan/radv_extensions.py b/src/amd/vulkan/radv_extensions.py index 0549a09..23c3265 100644 --- a/src/amd/vulkan/radv_extensions.py +++ b/src/amd/vulkan/radv_extensions.py @@ -122,6 +122,7 @@ EXTENSIONS = [ Extension('VK_EXT_calibrated_timestamps', 1, True), Extension('VK_EXT_conditional_rendering', 1, True), Extension('VK_EXT_conservative_rasterization', 1, 'device->rad_info.chip_class >= GFX9'), + Extension('VK_EXT_custom_border_color', 12, True), Extension('VK_EXT_display_surface_counter', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), Extension('VK_EXT_display_control', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), Extension('VK_EXT_debug_report', 9, True), diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 27d512a..d655fa0 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -781,6 +781,20 @@ struct radv_secure_compile_state { char *uid; }; +#define RADV_BORDER_COLOR_COUNT 4096 +#define RADV_BORDER_COLOR_BUFFER_SIZE (sizeof(VkClearColorValue) * RADV_BORDER_COLOR_COUNT) + +struct radv_device_border_color_data { + bool used[RADV_BORDER_COLOR_COUNT]; + + struct radeon_winsys_bo *bo; + VkClearColorValue *colors_gpu_ptr; + + /* Mutex is required to guarantee vkCreateSampler thread safety + * given that we are writing to a buffer and checking color occupation */ + pthread_mutex_t mutex; +}; + struct radv_device { struct vk_device vk; @@ -851,6 +865,8 @@ struct radv_device { /* Whether anisotropy is forced with RADV_TEX_ANISO (-1 is disabled). */ int force_aniso; + struct radv_device_border_color_data border_color_data; + struct radv_secure_compile_state *sc_state; /* Condition variable for legacy timelines, to notify waiters when a @@ -2162,6 +2178,7 @@ struct radv_sampler { struct vk_object_base base; uint32_t state[4]; struct radv_sampler_ycbcr_conversion *ycbcr_sampler; + uint32_t border_color_slot; }; struct radv_framebuffer { diff --git a/src/amd/vulkan/si_cmd_buffer.c b/src/amd/vulkan/si_cmd_buffer.c index 03fa89b..ad71ee5 100644 --- a/src/amd/vulkan/si_cmd_buffer.c +++ b/src/amd/vulkan/si_cmd_buffer.c @@ -456,6 +456,16 @@ si_emit_graphics(struct radv_device *device, radeon_set_context_reg(cs, R_028C5C_VGT_OUT_DEALLOC_CNTL, 16); } + if (device->border_color_data.bo) { + uint64_t border_color_va = radv_buffer_get_va(device->border_color_data.bo); + + radeon_set_context_reg(cs, R_028080_TA_BC_BASE_ADDR, border_color_va >> 8); + if (physical_device->rad_info.chip_class >= GFX7) { + radeon_set_context_reg(cs, R_028084_TA_BC_BASE_ADDR_HI, + S_028084_ADDRESS(border_color_va >> 40)); + } + } + if (physical_device->rad_info.chip_class >= GFX9) { radeon_set_context_reg(cs, R_028C48_PA_SC_BINNER_CNTL_1, S_028C48_MAX_ALLOC_COUNT(physical_device->rad_info.pbb_max_alloc_count - 1) | -- 2.7.4