From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 2 +- dlls/winevulkan/vulkan.c | 21 ++++++ dlls/winevulkan/vulkan_thunks.c | 130 ++++++++++++++++++++++++++++++-- dlls/winevulkan/vulkan_thunks.h | 1 + include/wine/vulkan.h | 30 ++++++++ 5 files changed, 177 insertions(+), 7 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index bf541199ef5..397efba567b 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -96,7 +96,6 @@ UNSUPPORTED_EXTENSIONS = [ # Device extensions "VK_AMD_display_native_hdr", "VK_EXT_full_screen_exclusive", - "VK_EXT_map_memory_placed", "VK_GOOGLE_display_timing", "VK_KHR_external_fence_win32", "VK_KHR_external_semaphore_win32", @@ -255,6 +254,7 @@ MANUAL_UNIX_THUNKS = { "vkGetPhysicalDeviceExternalFencePropertiesKHR", "vkGetPhysicalDeviceExternalSemaphoreProperties", "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR", + "vkGetPhysicalDeviceFeatures2KHR", "vkGetPhysicalDeviceImageFormatProperties2", "vkGetPhysicalDeviceImageFormatProperties2KHR", "vkGetPhysicalDevicePresentRectanglesKHR", diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 1d9cf8c1cac..e0d42757e3e 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -406,6 +406,7 @@ static VkResult wine_vk_device_convert_create_info(struct wine_phys_dev *phys_de { const char *extra_extensions[2], * const*extensions = src->ppEnabledExtensionNames; unsigned int i, extra_count = 0, extensions_count = src->enabledExtensionCount; + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *map_placed_features;
*dst = *src;
@@ -425,6 +426,10 @@ static VkResult wine_vk_device_convert_create_info(struct wine_phys_dev *phys_de } }
+ map_placed_features = find_next_struct(dst->pNext, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT); + if (map_placed_features && (map_placed_features->memoryMapPlaced || map_placed_features->memoryMapRangePlaced)) + return VK_ERROR_FEATURE_NOT_PRESENT; + if (phys_dev->external_memory_align) { if (!find_extension(extensions, extensions_count, "VK_KHR_external_memory")) @@ -1218,6 +1223,22 @@ VkResult wine_vkEnumeratePhysicalDeviceGroupsKHR(VkInstance handle, uint32_t *co instance->funcs.p_vkEnumeratePhysicalDeviceGroupsKHR, count, properties); }
+void wine_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice phys_dev_handle, VkPhysicalDeviceFeatures2 *features) +{ + struct wine_phys_dev *phys_dev = wine_phys_dev_from_handle(phys_dev_handle); + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *map_placed_features; + + phys_dev->instance->funcs.p_vkGetPhysicalDeviceFeatures2KHR(phys_dev->host_physical_device, features); + + map_placed_features = find_next_struct(features->pNext, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT); + if (map_placed_features) + { + map_placed_features->memoryMapPlaced = VK_FALSE; + map_placed_features->memoryMapRangePlaced = VK_FALSE; + } +} + void wine_vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice phys_dev, const VkPhysicalDeviceExternalFenceInfo *fence_info, VkExternalFenceProperties *properties) diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 13a211ecbc4..0dd526a4da7 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -3304,6 +3304,15 @@ typedef struct VkPhysicalDeviceShaderAtomicFloat16VectorFeaturesNV32 VkBool32 shaderFloat16VectorAtomics; } VkPhysicalDeviceShaderAtomicFloat16VectorFeaturesNV32;
+typedef struct VkPhysicalDeviceMapMemoryPlacedFeaturesEXT32 +{ + VkStructureType sType; + PTR32 pNext; + VkBool32 memoryMapPlaced; + VkBool32 memoryMapRangePlaced; + VkBool32 memoryUnmapReserve; +} VkPhysicalDeviceMapMemoryPlacedFeaturesEXT32; + typedef struct VkDeviceCreateInfo32 { VkStructureType sType; @@ -6392,6 +6401,13 @@ typedef struct VkPhysicalDeviceRenderPassStripedPropertiesARM32 uint32_t maxRenderPassStripes; } VkPhysicalDeviceRenderPassStripedPropertiesARM32;
+typedef struct VkPhysicalDeviceMapMemoryPlacedPropertiesEXT32 +{ + VkStructureType sType; + PTR32 pNext; + VkDeviceSize DECLSPEC_ALIGN(8) minPlacedMemoryMapAlignment; +} VkPhysicalDeviceMapMemoryPlacedPropertiesEXT32; + typedef struct VkPhysicalDeviceProperties232 { VkStructureType sType; @@ -6656,6 +6672,13 @@ typedef struct VkLatencySleepInfoNV32 uint64_t DECLSPEC_ALIGN(8) value; } VkLatencySleepInfoNV32;
+typedef struct VkMemoryMapPlacedInfoEXT32 +{ + VkStructureType sType; + PTR32 pNext; + PTR32 pPlacedAddress; +} VkMemoryMapPlacedInfoEXT32; + typedef struct VkMemoryMapInfoKHR32 { VkStructureType sType; @@ -13626,6 +13649,19 @@ static inline void convert_VkDeviceCreateInfo_win64_to_host(struct conversion_co out_header = (void *)out_ext; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT: + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *out_ext = conversion_context_alloc(ctx, sizeof(*out_ext)); + const VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *in_ext = (const VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *)in_header; + out_ext->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT; + out_ext->pNext = NULL; + out_ext->memoryMapPlaced = in_ext->memoryMapPlaced; + out_ext->memoryMapRangePlaced = in_ext->memoryMapRangePlaced; + out_ext->memoryUnmapReserve = in_ext->memoryUnmapReserve; + out_header->pNext = (void *)out_ext; + out_header = (void *)out_ext; + break; + } default: FIXME("Unhandled sType %u.\n", in_header->sType); break; @@ -15896,6 +15932,19 @@ static inline void convert_VkDeviceCreateInfo_win32_to_host(struct conversion_co out_header = (void *)out_ext; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT: + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *out_ext = conversion_context_alloc(ctx, sizeof(*out_ext)); + const VkPhysicalDeviceMapMemoryPlacedFeaturesEXT32 *in_ext = (const VkPhysicalDeviceMapMemoryPlacedFeaturesEXT32 *)in_header; + out_ext->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT; + out_ext->pNext = NULL; + out_ext->memoryMapPlaced = in_ext->memoryMapPlaced; + out_ext->memoryMapRangePlaced = in_ext->memoryMapRangePlaced; + out_ext->memoryUnmapReserve = in_ext->memoryUnmapReserve; + out_header->pNext = (void *)out_ext; + out_header = (void *)out_ext; + break; + } default: FIXME("Unhandled sType %u.\n", in_header->sType); break; @@ -23292,6 +23341,19 @@ static inline void convert_VkPhysicalDeviceFeatures2_win32_to_host(struct conver out_header = (void *)out_ext; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT: + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *out_ext = conversion_context_alloc(ctx, sizeof(*out_ext)); + const VkPhysicalDeviceMapMemoryPlacedFeaturesEXT32 *in_ext = (const VkPhysicalDeviceMapMemoryPlacedFeaturesEXT32 *)in_header; + out_ext->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT; + out_ext->pNext = NULL; + out_ext->memoryMapPlaced = in_ext->memoryMapPlaced; + out_ext->memoryMapRangePlaced = in_ext->memoryMapRangePlaced; + out_ext->memoryUnmapReserve = in_ext->memoryUnmapReserve; + out_header->pNext = (void *)out_ext; + out_header = (void *)out_ext; + break; + } default: FIXME("Unhandled sType %u.\n", in_header->sType); break; @@ -25122,6 +25184,17 @@ static inline void convert_VkPhysicalDeviceFeatures2_host_to_win32(const VkPhysi out_header = (void *)out_ext; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT: + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT32 *out_ext = find_next_struct32(out_header, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT); + const VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *in_ext = (const VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *)in_header; + out_ext->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT; + out_ext->memoryMapPlaced = in_ext->memoryMapPlaced; + out_ext->memoryMapRangePlaced = in_ext->memoryMapRangePlaced; + out_ext->memoryUnmapReserve = in_ext->memoryUnmapReserve; + out_header = (void *)out_ext; + break; + } default: break; } @@ -26568,6 +26641,15 @@ static inline void convert_VkPhysicalDeviceProperties2_win32_to_host(struct conv out_header = (void *)out_ext; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT: + { + VkPhysicalDeviceMapMemoryPlacedPropertiesEXT *out_ext = conversion_context_alloc(ctx, sizeof(*out_ext)); + out_ext->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT; + out_ext->pNext = NULL; + out_header->pNext = (void *)out_ext; + out_header = (void *)out_ext; + break; + } default: FIXME("Unhandled sType %u.\n", in_header->sType); break; @@ -27743,6 +27825,15 @@ static inline void convert_VkPhysicalDeviceProperties2_host_to_win32(const VkPhy out_header = (void *)out_ext; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT: + { + VkPhysicalDeviceMapMemoryPlacedPropertiesEXT32 *out_ext = find_next_struct32(out_header, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT); + const VkPhysicalDeviceMapMemoryPlacedPropertiesEXT *in_ext = (const VkPhysicalDeviceMapMemoryPlacedPropertiesEXT *)in_header; + out_ext->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT; + out_ext->minPlacedMemoryMapAlignment = in_ext->minPlacedMemoryMapAlignment; + out_header = (void *)out_ext; + break; + } default: break; } @@ -28656,8 +28747,11 @@ static inline void convert_VkLatencySleepInfoNV_win32_to_host(const VkLatencySle FIXME("Unexpected pNext\n"); }
-static inline void convert_VkMemoryMapInfoKHR_win32_to_unwrapped_host(const VkMemoryMapInfoKHR32 *in, VkMemoryMapInfoKHR *out) +static inline void convert_VkMemoryMapInfoKHR_win32_to_unwrapped_host(struct conversion_context *ctx, const VkMemoryMapInfoKHR32 *in, VkMemoryMapInfoKHR *out) { + const VkBaseInStructure32 *in_header; + VkBaseOutStructure *out_header = (void *)out; + if (!in) return;
out->sType = in->sType; @@ -28666,8 +28760,27 @@ static inline void convert_VkMemoryMapInfoKHR_win32_to_unwrapped_host(const VkMe out->memory = in->memory; out->offset = in->offset; out->size = in->size; - if (in->pNext) - FIXME("Unexpected pNext\n"); + + for (in_header = UlongToPtr(in->pNext); in_header; in_header = UlongToPtr(in_header->pNext)) + { + switch (in_header->sType) + { + case VK_STRUCTURE_TYPE_MEMORY_MAP_PLACED_INFO_EXT: + { + VkMemoryMapPlacedInfoEXT *out_ext = conversion_context_alloc(ctx, sizeof(*out_ext)); + const VkMemoryMapPlacedInfoEXT32 *in_ext = (const VkMemoryMapPlacedInfoEXT32 *)in_header; + out_ext->sType = VK_STRUCTURE_TYPE_MEMORY_MAP_PLACED_INFO_EXT; + out_ext->pNext = NULL; + out_ext->pPlacedAddress = (void *)UlongToPtr(in_ext->pPlacedAddress); + out_header->pNext = (void *)out_ext; + out_header = (void *)out_ext; + break; + } + default: + FIXME("Unhandled sType %u.\n", in_header->sType); + break; + } + } }
#ifdef _WIN64 @@ -42620,7 +42733,7 @@ static NTSTATUS thunk64_vkGetPhysicalDeviceFeatures2KHR(void *args)
TRACE("%p, %p\n", params->physicalDevice, params->pFeatures);
- wine_phys_dev_from_handle(params->physicalDevice)->instance->funcs.p_vkGetPhysicalDeviceFeatures2KHR(wine_phys_dev_from_handle(params->physicalDevice)->host_physical_device, params->pFeatures); + wine_vkGetPhysicalDeviceFeatures2KHR(params->physicalDevice, params->pFeatures); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -42640,7 +42753,7 @@ static NTSTATUS thunk32_vkGetPhysicalDeviceFeatures2KHR(void *args)
init_conversion_context(ctx); convert_VkPhysicalDeviceFeatures2_win32_to_host(ctx, (VkPhysicalDeviceFeatures232 *)UlongToPtr(params->pFeatures), &pFeatures_host); - wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->instance->funcs.p_vkGetPhysicalDeviceFeatures2KHR(wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->host_physical_device, &pFeatures_host); + wine_vkGetPhysicalDeviceFeatures2KHR((VkPhysicalDevice)UlongToPtr(params->physicalDevice), &pFeatures_host); convert_VkPhysicalDeviceFeatures2_host_to_win32(&pFeatures_host, (VkPhysicalDeviceFeatures232 *)UlongToPtr(params->pFeatures)); free_conversion_context(ctx); return STATUS_SUCCESS; @@ -44737,11 +44850,15 @@ static NTSTATUS thunk32_vkMapMemory2KHR(void *args) VkResult result; } *params = args; VkMemoryMapInfoKHR pMemoryMapInfo_host; + struct conversion_context local_ctx; + struct conversion_context *ctx = &local_ctx;
TRACE("%#x, %#x, %#x\n", params->device, params->pMemoryMapInfo, params->ppData);
- convert_VkMemoryMapInfoKHR_win32_to_unwrapped_host((const VkMemoryMapInfoKHR32 *)UlongToPtr(params->pMemoryMapInfo), &pMemoryMapInfo_host); + init_conversion_context(ctx); + convert_VkMemoryMapInfoKHR_win32_to_unwrapped_host(ctx, (const VkMemoryMapInfoKHR32 *)UlongToPtr(params->pMemoryMapInfo), &pMemoryMapInfo_host); params->result = wine_vkMapMemory2KHR((VkDevice)UlongToPtr(params->device), &pMemoryMapInfo_host, (void **)UlongToPtr(params->ppData)); + free_conversion_context(ctx); return STATUS_SUCCESS; }
@@ -46331,6 +46448,7 @@ static const char * const vk_device_extensions[] = "VK_EXT_legacy_dithering", "VK_EXT_line_rasterization", "VK_EXT_load_store_op_none", + "VK_EXT_map_memory_placed", "VK_EXT_memory_budget", "VK_EXT_memory_priority", "VK_EXT_mesh_shader", diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 2321bb91c09..dfd6ebdfeea 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -56,6 +56,7 @@ void wine_vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDe void wine_vkGetPhysicalDeviceExternalFencePropertiesKHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, VkExternalFenceProperties *pExternalFenceProperties); void wine_vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties); void wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties); +void wine_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2 *pFeatures); VkResult wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties); VkResult wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties); VkResult wine_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pRectCount, VkRect2D *pRects); diff --git a/include/wine/vulkan.h b/include/wine/vulkan.h index 4a38c58bd1c..568bc36e405 100644 --- a/include/wine/vulkan.h +++ b/include/wine/vulkan.h @@ -415,6 +415,8 @@ #define VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME "VK_EXT_host_image_copy" #define VK_KHR_MAP_MEMORY_2_SPEC_VERSION 1 #define VK_KHR_MAP_MEMORY_2_EXTENSION_NAME "VK_KHR_map_memory2" +#define VK_EXT_MAP_MEMORY_PLACED_SPEC_VERSION 1 +#define VK_EXT_MAP_MEMORY_PLACED_EXTENSION_NAME "VK_EXT_map_memory_placed" #define VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION 1 #define VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME "VK_EXT_shader_atomic_float2" #define VK_EXT_SURFACE_MAINTENANCE_1_SPEC_VERSION 1 @@ -2973,6 +2975,7 @@ typedef enum VkMemoryHeapFlagBits
typedef enum VkMemoryMapFlagBits { + VK_MEMORY_MAP_PLACED_BIT_EXT = 0x00000001, VK_MEMORY_MAP_FLAG_BITS_MAX_ENUM = 0x7fffffff, } VkMemoryMapFlagBits;
@@ -2999,6 +3002,7 @@ typedef enum VkMemoryPropertyFlagBits
typedef enum VkMemoryUnmapFlagBitsKHR { + VK_MEMORY_UNMAP_RESERVE_BIT_EXT = 0x00000001, VK_MEMORY_UNMAP_FLAG_BITS_KHR_MAX_ENUM = 0x7fffffff, } VkMemoryUnmapFlagBitsKHR;
@@ -4466,6 +4470,9 @@ typedef enum VkStructureType VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT = 1000270009, VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR = 1000271000, VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR = 1000271001, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT = 1000272000, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT = 1000272001, + VK_STRUCTURE_TYPE_MEMORY_MAP_PLACED_INFO_EXT = 1000272002, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT = 1000273000, VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT = 1000274000, VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT = 1000274001, @@ -7167,6 +7174,13 @@ typedef struct VkMemoryMapInfoKHR VkDeviceSize WINE_VK_ALIGN(8) size; } VkMemoryMapInfoKHR;
+typedef struct VkMemoryMapPlacedInfoEXT +{ + VkStructureType sType; + const void *pNext; + void *pPlacedAddress; +} VkMemoryMapPlacedInfoEXT; + typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo { VkStructureType sType; @@ -8803,6 +8817,22 @@ typedef struct VkPhysicalDeviceMaintenance6PropertiesKHR VkBool32 fragmentShadingRateClampCombinerInputs; } VkPhysicalDeviceMaintenance6PropertiesKHR;
+typedef struct VkPhysicalDeviceMapMemoryPlacedFeaturesEXT +{ + VkStructureType sType; + void *pNext; + VkBool32 memoryMapPlaced; + VkBool32 memoryMapRangePlaced; + VkBool32 memoryUnmapReserve; +} VkPhysicalDeviceMapMemoryPlacedFeaturesEXT; + +typedef struct VkPhysicalDeviceMapMemoryPlacedPropertiesEXT +{ + VkStructureType sType; + void *pNext; + VkDeviceSize WINE_VK_ALIGN(8) minPlacedMemoryMapAlignment; +} VkPhysicalDeviceMapMemoryPlacedPropertiesEXT; + typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT { VkStructureType sType;