Mesa (master): radv: Implement VK_EXT_custom_border_color

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri May 15 01:46:10 UTC 2020


Module: Mesa
Branch: master
Commit: 57e796a12a883f5845c8e0ed05ec6bdb6d055b53
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=57e796a12a883f5845c8e0ed05ec6bdb6d055b53

Author: Joshua Ashton <joshua at froggi.es>
Date:   Tue Apr  7 06:11:24 2020 +0100

radv: Implement VK_EXT_custom_border_color

Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4877>

---

 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 857b888ac41..3562f5c7122 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 bdfb2dad355..b4b429a4ed7 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 0549a09f377..23c32653651 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 27d512a5f49..d655fa07d9b 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 03fa89b74c7..ad71ee55ac2 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) |



More information about the mesa-commit mailing list