From 23a9339985d37db8c94fc71fe5ee6a11d368a1b9 Mon Sep 17 00:00:00 2001 From: Ella-0 Date: Wed, 28 Jul 2021 08:53:00 +0000 Subject: [PATCH] v3dv: Implement VK_EXT_custom_border_color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alejandro PiƱeiro Part-of: --- docs/features.txt | 2 +- src/broadcom/vulkan/v3dv_device.c | 22 +++++- src/broadcom/vulkan/v3dvx_device.c | 118 ++++++++++++++++++++++++++-- src/broadcom/vulkan/v3dvx_private.h | 3 +- 4 files changed, 136 insertions(+), 9 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index 2df031b18a2..e8396d4cb9e 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -511,7 +511,7 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_color_write_enable DONE (anv, lvp) VK_EXT_conditional_rendering DONE (anv, lvp, radv, tu) VK_EXT_conservative_rasterization DONE (anv/gen9+, radv) - VK_EXT_custom_border_color DONE (anv, lvp, radv, tu) + VK_EXT_custom_border_color DONE (anv, lvp, radv, tu, v3dv) VK_EXT_debug_marker DONE (radv) VK_EXT_depth_clip_enable DONE (anv, radv, tu) VK_EXT_depth_range_unrestricted DONE (radv) diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c index 524d1ddbcc1..52f3e2612cc 100644 --- a/src/broadcom/vulkan/v3dv_device.c +++ b/src/broadcom/vulkan/v3dv_device.c @@ -139,6 +139,7 @@ get_device_extensions(const struct v3dv_physical_device *device, .KHR_incremental_present = true, #endif .KHR_variable_pointers = true, + .EXT_custom_border_color = true, .EXT_external_memory_dma_buf = true, .EXT_index_type_uint8 = true, .EXT_physical_device_drm = true, @@ -1071,6 +1072,14 @@ v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, vk_foreach_struct(ext, pFeatures->pNext) { switch (ext->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: { + VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = + (VkPhysicalDeviceCustomBorderColorFeaturesEXT *)ext; + features->customBorderColors = true; + features->customBorderColorWithoutFormat = false; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR: { VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR *features = (VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR *)ext; @@ -1386,6 +1395,12 @@ v3dv_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, vk_foreach_struct(ext, pProperties->pNext) { switch (ext->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: { + VkPhysicalDeviceCustomBorderColorPropertiesEXT *props = + (VkPhysicalDeviceCustomBorderColorPropertiesEXT *)ext; + props->maxCustomBorderColorSamplers = V3D_MAX_TEXTURE_SAMPLERS; + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: { VkPhysicalDeviceIDProperties *id_props = (VkPhysicalDeviceIDProperties *)ext; @@ -2528,7 +2543,12 @@ v3dv_CreateSampler(VkDevice _device, sampler->compare_enable = pCreateInfo->compareEnable; sampler->unnormalized_coordinates = pCreateInfo->unnormalizedCoordinates; - v3dv_X(device, pack_sampler_state)(sampler, pCreateInfo); + + const VkSamplerCustomBorderColorCreateInfoEXT *bc_info = + vk_find_struct_const(pCreateInfo->pNext, + SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT); + + v3dv_X(device, pack_sampler_state)(sampler, pCreateInfo, bc_info); *pSampler = v3dv_sampler_to_handle(sampler); diff --git a/src/broadcom/vulkan/v3dvx_device.c b/src/broadcom/vulkan/v3dvx_device.c index d54c0a37d9f..f75b30e5477 100644 --- a/src/broadcom/vulkan/v3dvx_device.c +++ b/src/broadcom/vulkan/v3dvx_device.c @@ -28,6 +28,7 @@ #include "broadcom/compiler/v3d_compiler.h" #include "vk_format_info.h" #include "util/u_pack_color.h" +#include "util/half_float.h" static const enum V3DX(Wrap_Mode) vk_to_v3d_wrap_mode[] = { [VK_SAMPLER_ADDRESS_MODE_REPEAT] = V3D_WRAP_MODE_REPEAT, @@ -49,17 +50,109 @@ vk_to_v3d_compare_func[] = { [VK_COMPARE_OP_ALWAYS] = V3D_COMPARE_FUNC_ALWAYS, }; + +static union pipe_color_union encode_border_color( + const VkSamplerCustomBorderColorCreateInfoEXT *bc_info) +{ + const struct util_format_description *desc = + vk_format_description(bc_info->format); + + const struct v3dv_format *format = v3dX(get_format)(bc_info->format); + + union pipe_color_union border; + for (int i = 0; i < 4; i++) { + if (format->swizzle[i] <= 3) + border.ui[i] = bc_info->customBorderColor.uint32[format->swizzle[i]]; + else + border.ui[i] = 0; + } + + /* handle clamping */ + if (vk_format_has_depth(bc_info->format) && + vk_format_has_stencil(bc_info->format)) { + border.f[0] = CLAMP(border.f[0], 0, 1); + border.ui[1] = CLAMP(border.ui[1], 0, 0xff); + } else if (vk_format_is_unorm(bc_info->format)) { + for (int i = 0; i < 4; i++) + border.f[i] = CLAMP(border.f[i], 0, 1); + } else if (vk_format_is_snorm(bc_info->format)) { + for (int i = 0; i < 4; i++) + border.f[i] = CLAMP(border.f[i], -1, 1); + } else if (vk_format_is_uint(bc_info->format) && + desc->channel[0].size < 32) { + for (int i = 0; i < 4; i++) + border.ui[i] = CLAMP(border.ui[i], 0, (1 << desc->channel[i].size)); + } else if (vk_format_is_sint(bc_info->format) && + desc->channel[0].size < 32) { + for (int i = 0; i < 4; i++) + border.i[i] = CLAMP(border.i[i], + -(1 << (desc->channel[i].size - 1)), + (1 << (desc->channel[i].size - 1)) - 1); + } + + /* convert from float to expected format */ + if (vk_format_is_srgb(bc_info->format) || + vk_format_is_compressed(bc_info->format)) { + for (int i = 0; i < 4; i++) + border.ui[i] = _mesa_float_to_half(border.f[i]); + } else if (vk_format_is_unorm(bc_info->format)) { + for (int i = 0; i < 4; i++) { + switch (desc->channel[i].size) { + case 8: + case 16: + /* expect u16 for non depth values */ + if (!vk_format_has_depth(bc_info->format)) + border.ui[i] = (uint32_t) (border.f[i] * (float) 0xffff); + break; + case 24: + case 32: + /* uses full f32; no conversion needed */ + break; + default: + border.ui[i] = _mesa_float_to_half(border.f[i]); + break; + } + } + } else if (vk_format_is_snorm(bc_info->format)) { + for (int i = 0; i < 4; i++) { + switch (desc->channel[i].size) { + case 8: + border.ui[i] = (int32_t) (border.f[i] * (float) 0x3fff); + break; + case 16: + border.i[i] = (int32_t) (border.f[i] * (float) 0x7fff); + break; + case 24: + case 32: + /* uses full f32; no conversion needed */ + break; + default: + border.ui[i] = _mesa_float_to_half(border.f[i]); + break; + } + } + } else if (vk_format_is_float(bc_info->format)) { + for (int i = 0; i < 4; i++) { + switch(desc->channel[i].size) { + case 16: + border.ui[i] = _mesa_float_to_half(border.f[i]); + break; + default: + break; + } + } + } + + return border; +} + void v3dX(pack_sampler_state)(struct v3dv_sampler *sampler, - const VkSamplerCreateInfo *pCreateInfo) + const VkSamplerCreateInfo *pCreateInfo, + const VkSamplerCustomBorderColorCreateInfoEXT *bc_info) { enum V3DX(Border_Color_Mode) border_color_mode; - /* For now we only support the preset Vulkan border color modes. If we - * want to implement VK_EXT_custom_border_color in the future we would have - * to use V3D_BORDER_COLOR_FOLLOWS, and fill up border_color_word_[0/1/2/3] - * SAMPLER_STATE. - */ switch (pCreateInfo->borderColor) { case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: @@ -73,6 +166,10 @@ v3dX(pack_sampler_state)(struct v3dv_sampler *sampler, case VK_BORDER_COLOR_INT_OPAQUE_WHITE: border_color_mode = V3D_BORDER_COLOR_1111; break; + case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: + case VK_BORDER_COLOR_INT_CUSTOM_EXT: + border_color_mode = V3D_BORDER_COLOR_FOLLOWS; + break; default: unreachable("Unknown border color"); break; @@ -106,6 +203,15 @@ v3dX(pack_sampler_state)(struct v3dv_sampler *sampler, s.border_color_mode = border_color_mode; + if (s.border_color_mode == V3D_BORDER_COLOR_FOLLOWS) { + union pipe_color_union border = encode_border_color(bc_info); + + s.border_color_word_0 = border.ui[0]; + s.border_color_word_1 = border.ui[1]; + s.border_color_word_2 = border.ui[2]; + s.border_color_word_3 = border.ui[3]; + } + s.wrap_i_border = false; /* Also hardcoded on v3d */ s.wrap_s = vk_to_v3d_wrap_mode[pCreateInfo->addressModeU]; s.wrap_t = vk_to_v3d_wrap_mode[pCreateInfo->addressModeV]; diff --git a/src/broadcom/vulkan/v3dvx_private.h b/src/broadcom/vulkan/v3dvx_private.h index edebf251833..b74824a58d8 100644 --- a/src/broadcom/vulkan/v3dvx_private.h +++ b/src/broadcom/vulkan/v3dvx_private.h @@ -130,7 +130,8 @@ v3dX(cmd_buffer_render_pass_setup_render_target)(struct v3dv_cmd_buffer *cmd_buf void v3dX(pack_sampler_state)(struct v3dv_sampler *sampler, - const VkSamplerCreateInfo *pCreateInfo); + const VkSamplerCreateInfo *pCreateInfo, + const VkSamplerCustomBorderColorCreateInfoEXT *bc_info); void v3dX(framebuffer_compute_internal_bpp_msaa)(const struct v3dv_framebuffer *framebuffer,