break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
+ VkPhysicalDeviceCustomBorderColorFeaturesEXT *features =
+ (VkPhysicalDeviceCustomBorderColorFeaturesEXT *)ext;
+ features->customBorderColors = pdevice->info.gen >= 8;
+ features->customBorderColorWithoutFormat = pdevice->info.gen >= 8;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
(VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
#define MAX_PER_STAGE_DESCRIPTOR_INPUT_ATTACHMENTS 64
#define MAX_DESCRIPTOR_SET_INPUT_ATTACHMENTS 256
+#define MAX_CUSTOM_BORDER_COLORS 4096
+
void anv_GetPhysicalDeviceProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties)
vk_foreach_struct(ext, pProperties->pNext) {
switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: {
+ VkPhysicalDeviceCustomBorderColorPropertiesEXT *properties =
+ (VkPhysicalDeviceCustomBorderColorPropertiesEXT *)ext;
+ properties->maxCustomBorderColorSamplers = MAX_CUSTOM_BORDER_COLORS;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR: {
VkPhysicalDeviceDepthStencilResolvePropertiesKHR *properties =
(VkPhysicalDeviceDepthStencilResolvePropertiesKHR *)ext;
return state;
}
-/* Haswell border color is a bit of a disaster. Float and unorm formats use a
- * straightforward 32-bit float color in the first 64 bytes. Instead of using
- * a nice float/integer union like Gen8+, Haswell specifies the integer border
- * color as a separate entry /after/ the float color. The layout of this entry
- * also depends on the format's bpp (with extra hacks for RG32), and overlaps.
- *
- * Since we don't know the format/bpp, we can't make any of the border colors
- * containing '1' work for all formats, as it would be in the wrong place for
- * some of them. We opt to make 32-bit integers work as this seems like the
- * most common option. Fortunately, transparent black works regardless, as
- * all zeroes is the same in every bit-size.
- */
-struct hsw_border_color {
- float float32[4];
- uint32_t _pad0[12];
- uint32_t uint32[4];
- uint32_t _pad1[108];
-};
-
-struct gen8_border_color {
- union {
- float float32[4];
- uint32_t uint32[4];
- };
- /* Pad out to 64 bytes */
- uint32_t _pad[12];
-};
-
static void
anv_device_init_border_colors(struct anv_device *device)
{
if (result != VK_SUCCESS)
goto fail_batch_bo_pool;
+ if (device->info.gen >= 8) {
+ /* The border color pointer is limited to 24 bits, so we need to make
+ * sure that any such color used at any point in the program doesn't
+ * exceed that limit.
+ * We achieve that by reserving all the custom border colors we support
+ * right off the bat, so they are close to the base address.
+ */
+ anv_state_reserved_pool_init(&device->custom_border_colors,
+ &device->dynamic_state_pool,
+ sizeof(struct gen8_border_color),
+ MAX_CUSTOM_BORDER_COLORS, 64);
+ }
+
result = anv_state_pool_init(&device->instruction_state_pool, device,
INSTRUCTION_STATE_POOL_MIN_ADDRESS, 0, 16384);
if (result != VK_SUCCESS)
fail_instruction_state_pool:
anv_state_pool_finish(&device->instruction_state_pool);
fail_dynamic_state_pool:
+ if (device->info.gen >= 8)
+ anv_state_reserved_pool_finish(&device->custom_border_colors);
anv_state_pool_finish(&device->dynamic_state_pool);
fail_batch_bo_pool:
anv_bo_pool_finish(&device->batch_bo_pool);
/* We only need to free these to prevent valgrind errors. The backing
* BO will go away in a couple of lines so we don't actually leak.
*/
+ if (device->info.gen >= 8)
+ anv_state_reserved_pool_finish(&device->custom_border_colors);
anv_state_pool_free(&device->dynamic_state_pool, device->border_colors);
anv_state_pool_free(&device->dynamic_state_pool, device->slice_hash);
#endif
sampler->bindless_state);
}
+ if (sampler->custom_border_color.map) {
+ anv_state_reserved_pool_free(&device->custom_border_colors,
+ sampler->custom_border_color);
+ }
+
vk_object_base_finish(&sampler->base);
vk_free2(&device->vk.alloc, pAllocator, sampler);
}
struct anv_state_pool binding_table_pool;
struct anv_state_pool surface_state_pool;
+ struct anv_state_reserved_pool custom_border_colors;
+
/** BO used for various workarounds
*
* There are a number of workarounds on our hardware which require writing
}
+/* Haswell border color is a bit of a disaster. Float and unorm formats use a
+ * straightforward 32-bit float color in the first 64 bytes. Instead of using
+ * a nice float/integer union like Gen8+, Haswell specifies the integer border
+ * color as a separate entry /after/ the float color. The layout of this entry
+ * also depends on the format's bpp (with extra hacks for RG32), and overlaps.
+ *
+ * Since we don't know the format/bpp, we can't make any of the border colors
+ * containing '1' work for all formats, as it would be in the wrong place for
+ * some of them. We opt to make 32-bit integers work as this seems like the
+ * most common option. Fortunately, transparent black works regardless, as
+ * all zeroes is the same in every bit-size.
+ */
+struct hsw_border_color {
+ float float32[4];
+ uint32_t _pad0[12];
+ uint32_t uint32[4];
+ uint32_t _pad1[108];
+};
+
+struct gen8_border_color {
+ union {
+ float float32[4];
+ uint32_t uint32[4];
+ };
+ /* Pad out to 64 bytes */
+ uint32_t _pad[12];
+};
+
struct anv_ycbcr_conversion {
struct vk_object_base base;
* and with a 32-byte stride for use as bindless samplers.
*/
struct anv_state bindless_state;
+
+ struct anv_state custom_border_color;
};
struct anv_framebuffer {
sampler->n_planes = 1;
uint32_t border_color_stride = GEN_IS_HASWELL ? 512 : 64;
- uint32_t border_color_offset = device->border_colors.offset +
- pCreateInfo->borderColor *
- border_color_stride;
+ uint32_t border_color_offset;
+ ASSERTED bool has_custom_color = false;
+ if (pCreateInfo->borderColor <= VK_BORDER_COLOR_INT_OPAQUE_WHITE) {
+ border_color_offset = device->border_colors.offset +
+ pCreateInfo->borderColor *
+ border_color_stride;
+ } else {
+ assert(GEN_GEN >= 8);
+ sampler->custom_border_color =
+ anv_state_reserved_pool_alloc(&device->custom_border_colors);
+ border_color_offset = sampler->custom_border_color.offset;
+ }
#if GEN_GEN >= 9
unsigned sampler_reduction_mode = STD_FILTER;
break;
}
#endif
+ case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT: {
+ VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color =
+ (VkSamplerCustomBorderColorCreateInfoEXT *) ext;
+ if (sampler->custom_border_color.map == NULL)
+ break;
+ struct gen8_border_color *cbc = sampler->custom_border_color.map;
+ if (custom_border_color->format == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
+ /* B4G4R4A4_UNORM_PACK16 is treated as R4G4B4A4_UNORM_PACK16 with
+ * a swizzle, but this does not carry over to the sampler for
+ * border colors, so we need to do the swizzle ourselves here.
+ */
+ cbc->uint32[0] = custom_border_color->customBorderColor.uint32[2];
+ cbc->uint32[1] = custom_border_color->customBorderColor.uint32[1];
+ cbc->uint32[2] = custom_border_color->customBorderColor.uint32[0];
+ cbc->uint32[3] = custom_border_color->customBorderColor.uint32[3];
+ } else {
+ /* Both structs share the same layout, so just copy them over. */
+ memcpy(cbc, &custom_border_color->customBorderColor,
+ sizeof(VkClearColorValue));
+ }
+ has_custom_color = true;
+ break;
+ }
default:
anv_debug_ignored_stype(ext->sType);
break;
}
}
+ assert((sampler->custom_border_color.map == NULL) || has_custom_color);
+
if (device->physical->has_bindless_samplers) {
/* If we have bindless, allocate enough samplers. We allocate 32 bytes
* for each sampler instead of 16 bytes because we want all bindless