#include "generated/chassis.h"
#include "object_lifetime_validation.h"
#include "generated/layer_chassis_dispatch.h"
uint64_t object_track_index = …;
VulkanTypedHandle ObjTrackStateTypedHandle(const ObjTrackState &track_state) { … }
bool ObjectLifetimes::TracksObject(uint64_t object_handle, VulkanObjectType object_type) const { … }
bool ObjectLifetimes::CheckObjectValidity(uint64_t object_handle, VulkanObjectType object_type, const char *invalid_handle_vuid,
const char *wrong_parent_vuid, const Location &loc, VulkanObjectType parent_type) const { … }
bool ObjectLifetimes::CheckPipelineObjectValidity(uint64_t object_handle, const char *invalid_handle_vuid,
const Location &loc) const { … }
void ObjectLifetimes::DestroyObjectSilently(uint64_t object, VulkanObjectType object_type) { … }
void ObjectLifetimes::DestroyQueueDataStructures() { … }
void ObjectLifetimes::DestroyUndestroyedObjects(VulkanObjectType object_type) { … }
bool ObjectLifetimes::ValidateAnonymousObject(uint64_t object, VkObjectType core_object_type, const char *invalid_handle_vuid,
const char *wrong_parent_vuid, const Location &loc) const { … }
void ObjectLifetimes::AllocateCommandBuffer(const VkCommandPool command_pool, const VkCommandBuffer command_buffer,
VkCommandBufferLevel level, const Location &loc) { … }
bool ObjectLifetimes::ValidateCommandBuffer(VkCommandPool command_pool, VkCommandBuffer command_buffer, const Location &loc) const { … }
void ObjectLifetimes::AllocateDescriptorSet(VkDescriptorPool descriptor_pool, VkDescriptorSet descriptor_set, const Location &loc) { … }
bool ObjectLifetimes::ValidateDescriptorSet(VkDescriptorPool descriptor_pool, VkDescriptorSet descriptor_set,
const Location &loc) const { … }
bool ObjectLifetimes::ValidateDescriptorWrite(VkWriteDescriptorSet const *desc, bool isPush, const Location &loc) const { … }
bool ObjectLifetimes::PreCallValidateCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount,
const VkWriteDescriptorSet *pDescriptorWrites,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateCmdPushDescriptorSet2KHR(VkCommandBuffer commandBuffer,
const VkPushDescriptorSetInfoKHR *pPushDescriptorSetInfo,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::CreateQueue(VkQueue vkObj, const Location &loc) { … }
void ObjectLifetimes::CreateSwapchainImageObject(VkImage swapchain_image, VkSwapchainKHR swapchain, const Location &loc) { … }
bool ObjectLifetimes::ReportLeakedInstanceObjects(VkInstance instance, VulkanObjectType object_type, const std::string &error_code,
const Location &loc) const { … }
bool ObjectLifetimes::ReportLeakedDeviceObjects(VkDevice device, VulkanObjectType object_type, const std::string &error_code,
const Location &loc) const { … }
bool ObjectLifetimes::PreCallValidateDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PreCallRecordDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator,
const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 *pQueueInfo, VkQueue *pQueue,
const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
const VkWriteDescriptorSet *pDescriptorWrites,
uint32_t descriptorCopyCount,
const VkCopyDescriptorSet *pDescriptorCopies,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
VkDescriptorPoolResetFlags flags, const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PreCallRecordResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
VkDescriptorPoolResetFlags flags, const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *begin_info,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
VkImage *pSwapchainImages, const RecordObject &record_obj) { … }
bool ObjectLifetimes::ValidateDescriptorSetLayoutCreateInfo(const VkDescriptorSetLayoutCreateInfo &create_info,
const Location &create_info_loc) const { … }
bool ObjectLifetimes::PreCallValidateCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorSetLayout *pSetLayout,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateGetDescriptorSetLayoutSupport(VkDevice device,
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
VkDescriptorSetLayoutSupport *pSupport,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
uint32_t *pQueueFamilyPropertyCount,
VkQueueFamilyProperties *pQueueFamilyProperties,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
uint32_t *pQueueFamilyPropertyCount,
VkQueueFamilyProperties *pQueueFamilyProperties,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
VkInstance *pInstance, const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
VkCommandBuffer *pCommandBuffers, const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
VkCommandBuffer *pCommandBuffers, const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
VkDescriptorSet *pDescriptorSets, const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
VkDescriptorSet *pDescriptorSets, const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
const VkCommandBuffer *pCommandBuffers,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PreCallRecordFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
const VkCommandBuffer *pCommandBuffers, const RecordObject &record_obj) { … }
void ObjectLifetimes::PreCallRecordDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
const VkAllocationCallbacks *pAllocator, const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PreCallRecordFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount,
const VkDescriptorSet *pDescriptorSets, const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
const VkAllocationCallbacks *pAllocator,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PreCallRecordDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
const VkAllocationCallbacks *pAllocator, const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateDestroyCommandPool(VkDevice device, VkCommandPool commandPool,
const VkAllocationCallbacks *pAllocator,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PreCallRecordDestroyCommandPool(VkDevice device, VkCommandPool commandPool,
const VkAllocationCallbacks *pAllocator, const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
uint32_t *pQueueFamilyPropertyCount,
VkQueueFamilyProperties2 *pQueueFamilyProperties,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,
uint32_t *pQueueFamilyPropertyCount,
VkQueueFamilyProperties2 *pQueueFamilyProperties,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
uint32_t *pQueueFamilyPropertyCount,
VkQueueFamilyProperties2 *pQueueFamilyProperties,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,
uint32_t *pQueueFamilyPropertyCount,
VkQueueFamilyProperties2 *pQueueFamilyProperties,
const RecordObject &record_obj) { … }
void ObjectLifetimes::AllocateDisplayKHR(VkPhysicalDevice physical_device, VkDisplayKHR display, const Location &loc) { … }
void ObjectLifetimes::PostCallRecordGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
VkDisplayPropertiesKHR *pProperties,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
uint32_t *pPropertyCount, VkDisplayModePropertiesKHR *pProperties,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordGetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
uint32_t *pPropertyCount,
VkDisplayProperties2KHR *pProperties,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordGetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
uint32_t *pPropertyCount, VkDisplayModeProperties2KHR *pProperties,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,
uint32_t *pPropertyCount,
VkDisplayPlanePropertiesKHR *pProperties,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordGetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice physicalDevice,
uint32_t *pPropertyCount,
VkDisplayPlaneProperties2KHR *pProperties,
const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateDebugMarkerSetObjectTagEXT(VkDevice device, const VkDebugMarkerObjectTagInfoEXT *pTagInfo,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateDebugMarkerSetObjectNameEXT(VkDevice device, const VkDebugMarkerObjectNameInfoEXT *pNameInfo,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateSetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateCreateDescriptorUpdateTemplate(VkDevice device,
const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateCreateDescriptorUpdateTemplateKHR(VkDevice device,
const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordCreateDescriptorUpdateTemplate(VkDevice device,
const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PostCallRecordCreateDescriptorUpdateTemplateKHR(VkDevice device,
const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate,
const RecordObject &record_obj) { … }
bool ObjectLifetimes::ValidateAccelerationStructures(const char *src_handle_vuid, const char *dst_handle_vuid, uint32_t count,
const VkAccelerationStructureBuildGeometryInfoKHR *infos,
const Location &loc) const { … }
bool ObjectLifetimes::PreCallValidateCmdBuildAccelerationStructuresKHR(
VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
const VkAccelerationStructureBuildRangeInfoKHR *const *ppBuildRangeInfos, const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateCmdBuildAccelerationStructuresIndirectKHR(
VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
const VkDeviceAddress *pIndirectDeviceAddresses, const uint32_t *pIndirectStrides, const uint32_t *const *ppMaxPrimitiveCounts,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateBuildAccelerationStructuresKHR(
VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount,
const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
const VkAccelerationStructureBuildRangeInfoKHR *const *ppBuildRangeInfos, const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
VkPipelineCache pipelineCache, uint32_t createInfoCount,
const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordCreateRayTracingPipelinesKHR(
VkDevice device, VkDeferredOperationKHR deferredOperation, VkPipelineCache pipelineCache, uint32_t createInfoCount,
const VkRayTracingPipelineCreateInfoKHR *pCreateInfos, const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
const RecordObject &record_obj, PipelineStates &pipeline_states,
std::shared_ptr<chassis::CreateRayTracingPipelinesKHR> chassis_state) { … }
#ifdef VK_USE_PLATFORM_METAL_EXT
bool ObjectLifetimes::PreCallValidateExportMetalObjectsEXT(VkDevice device, VkExportMetalObjectsInfoEXT *pMetalObjectsInfo,
const ErrorObject &error_obj) const {
bool skip = false;
const VkBaseOutStructure *metal_objects_info_ptr = reinterpret_cast<const VkBaseOutStructure *>(pMetalObjectsInfo->pNext);
while (metal_objects_info_ptr) {
switch (metal_objects_info_ptr->sType) {
case VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT: {
auto metal_command_queue_ptr = reinterpret_cast<const VkExportMetalCommandQueueInfoEXT *>(metal_objects_info_ptr);
skip |= ValidateObject(metal_command_queue_ptr->queue, kVulkanObjectTypeQueue, false,
"VUID-VkExportMetalCommandQueueInfoEXT-queue-parameter", kVUIDUndefined, error_obj.location);
} break;
case VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT: {
auto metal_buffer_ptr = reinterpret_cast<const VkExportMetalBufferInfoEXT *>(metal_objects_info_ptr);
skip |= ValidateObject(metal_buffer_ptr->memory, kVulkanObjectTypeDeviceMemory, false,
"VUID-VkExportMetalBufferInfoEXT-memory-parameter", kVUIDUndefined, error_obj.location);
} break;
case VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT: {
auto metal_texture_ptr = reinterpret_cast<const VkExportMetalTextureInfoEXT *>(metal_objects_info_ptr);
skip |= ValidateObject(metal_texture_ptr->image, kVulkanObjectTypeImage, true,
"VUID-VkExportMetalTextureInfoEXT-image-parameter",
"VUID-VkExportMetalTextureInfoEXT-commonparent", error_obj.location);
skip |= ValidateObject(metal_texture_ptr->imageView, kVulkanObjectTypeImageView, true,
"VUID-VkExportMetalTextureInfoEXT-imageView-parameter",
"VUID-VkExportMetalTextureInfoEXT-commonparent", error_obj.location);
skip |= ValidateObject(metal_texture_ptr->bufferView, kVulkanObjectTypeBufferView, true,
"VUID-VkExportMetalTextureInfoEXT-bufferView-parameter",
"VUID-VkExportMetalTextureInfoEXT-commonparent", error_obj.location);
} break;
case VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT: {
auto metal_iosurface_ptr = reinterpret_cast<const VkExportMetalIOSurfaceInfoEXT *>(metal_objects_info_ptr);
skip |= ValidateObject(metal_iosurface_ptr->image, kVulkanObjectTypeImage, false,
"VUID-VkExportMetalIOSurfaceInfoEXT-image-parameter", kVUIDUndefined, error_obj.location);
} break;
case VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT: {
auto metal_shared_event_ptr = reinterpret_cast<const VkExportMetalSharedEventInfoEXT *>(metal_objects_info_ptr);
skip |= ValidateObject(metal_shared_event_ptr->semaphore, kVulkanObjectTypeSemaphore, true,
"VUID-VkExportMetalSharedEventInfoEXT-semaphore-parameter",
"VUID-VkExportMetalSharedEventInfoEXT-commonparent", error_obj.location);
skip |= ValidateObject(metal_shared_event_ptr->event, kVulkanObjectTypeEvent, true,
"VUID-VkExportMetalSharedEventInfoEXT-event-parameter",
"VUID-VkExportMetalSharedEventInfoEXT-commonparent", error_obj.location);
} break;
default:
break;
}
metal_objects_info_ptr = metal_objects_info_ptr->pNext;
}
return skip;
}
#endif
bool ObjectLifetimes::PreCallValidateGetDescriptorEXT(VkDevice device, const VkDescriptorGetInfoEXT *pDescriptorInfo,
size_t dataSize, void *pDescriptor, const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateSetPrivateData(VkDevice device, VkObjectType objectType, uint64_t objectHandle,
VkPrivateDataSlot privateDataSlot, uint64_t data,
const ErrorObject &error_obj) const { … }
bool ObjectLifetimes::PreCallValidateGetPrivateData(VkDevice device, VkObjectType objectType, uint64_t objectHandle,
VkPrivateDataSlot privateDataSlot, uint64_t *pData,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkGraphicsPipelineCreateInfo *pCreateInfos,
const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
const RecordObject &record_obj) { … }
void ObjectLifetimes::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator,
const RecordObject &record_obj) { … }
bool ObjectLifetimes::PreCallValidateReleaseCapturedPipelineDataKHR(VkDevice device,
const VkReleaseCapturedPipelineDataInfoKHR *pInfo,
const VkAllocationCallbacks *pAllocator,
const ErrorObject &error_obj) const { … }
void ObjectLifetimes::PostCallRecordCreatePipelineBinariesKHR(VkDevice device, const VkPipelineBinaryCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineBinaryHandlesInfoKHR *pBinaries,
const RecordObject &record_obj) { … }