Support the VK_EXT_texel_buffer_alignment extension.
This extension lets implementations report separate limits for uniform and storage texel buffers, as well as whether or not the required alignment is only a single texel of the buffer view's format. This information is available in Metal, but only through an API query. We must query the required alignment for every buffer view format we support. Update Vulkan-Headers to pull in support for this new extension.
This commit is contained in:
parent
fe3b2fbd5f
commit
7771b00bee
@ -253,12 +253,13 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following
|
||||
- `VK_EXT_debug_report`
|
||||
- `VK_EXT_debug_utils`
|
||||
- `VK_EXT_host_query_reset`
|
||||
- `VK_EXT_memory_budget`
|
||||
- `VK_EXT_memory_budget` *(requires Metal 2.0)*
|
||||
- `VK_EXT_metal_surface`
|
||||
- `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)*
|
||||
- `VK_EXT_shader_viewport_index_layer`
|
||||
- `VK_EXT_swapchain_colorspace` *(macOS)*
|
||||
- `VK_EXT_vertex_attribute_divisor`
|
||||
- `VK_EXT_texel_buffer_alignment` *(requires Metal 2.0)*
|
||||
- `VK_EXTX_portability_subset`
|
||||
- `VK_MVK_ios_surface` *(iOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*
|
||||
- `VK_MVK_macos_surface` *(macOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*
|
||||
|
@ -1 +1 @@
|
||||
097a1045098213919fd56442f52c716fc78eeb27
|
||||
737f4c1cd96283747967c2024a0108b742214455
|
||||
|
@ -336,6 +336,7 @@ protected:
|
||||
VkPhysicalDeviceFeatures _features;
|
||||
MVKPhysicalDeviceMetalFeatures _metalFeatures;
|
||||
VkPhysicalDeviceProperties _properties;
|
||||
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT _texelBuffAlignProperties;
|
||||
VkPhysicalDeviceMemoryProperties _memoryProperties;
|
||||
std::vector<MVKQueueFamily*> _queueFamilies;
|
||||
uint32_t _allMemoryTypes;
|
||||
|
@ -69,8 +69,7 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
|
||||
if (features) {
|
||||
features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
features->features = _features;
|
||||
auto* next = (VkBaseOutStructure*)features->pNext;
|
||||
while (next) {
|
||||
for (auto* next = (VkBaseOutStructure*)features->pNext; next; next = next->pNext) {
|
||||
switch ((uint32_t)next->sType) {
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
|
||||
auto* storageFeatures = (VkPhysicalDevice16BitStorageFeatures*)next;
|
||||
@ -109,6 +108,11 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
|
||||
hostQueryResetFeatures->hostQueryReset = true;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT: {
|
||||
auto* texelBuffAlignFeatures = (VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT*)next;
|
||||
texelBuffAlignFeatures->texelBufferAlignment = _metalFeatures.texelBuffers && [_mtlDevice respondsToSelector: @selector(minimumLinearTextureAlignmentForPixelFormat:)];
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
|
||||
auto* divisorFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next;
|
||||
divisorFeatures->vertexAttributeInstanceRateDivisor = true;
|
||||
@ -127,7 +131,6 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
next = next->pNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -140,42 +143,44 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
|
||||
if (properties) {
|
||||
properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
properties->properties = _properties;
|
||||
auto* next = (MVKVkAPIStructHeader*)properties->pNext;
|
||||
while (next) {
|
||||
for (auto* next = (VkBaseOutStructure*)properties->pNext; next; next = next->pNext) {
|
||||
switch ((uint32_t)next->sType) {
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
|
||||
auto* pointClipProps = (VkPhysicalDevicePointClippingProperties*)next;
|
||||
pointClipProps->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
|
||||
next = (MVKVkAPIStructHeader*)pointClipProps->pNext;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
|
||||
auto* maint3Props = (VkPhysicalDeviceMaintenance3Properties*)next;
|
||||
maint3Props->maxPerSetDescriptors = (_metalFeatures.maxPerStageBufferCount + _metalFeatures.maxPerStageTextureCount + _metalFeatures.maxPerStageSamplerCount) * 2;
|
||||
maint3Props->maxPerSetDescriptors = (_metalFeatures.maxPerStageBufferCount + _metalFeatures.maxPerStageTextureCount + _metalFeatures.maxPerStageSamplerCount) * 4;
|
||||
maint3Props->maxMemoryAllocationSize = _metalFeatures.maxMTLBufferSize;
|
||||
next = (MVKVkAPIStructHeader*)maint3Props->pNext;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
|
||||
auto* pushDescProps = (VkPhysicalDevicePushDescriptorPropertiesKHR*)next;
|
||||
pushDescProps->maxPushDescriptors = _properties.limits.maxPerStageResources;
|
||||
next = (MVKVkAPIStructHeader*)pushDescProps->pNext;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT: {
|
||||
auto* texelBuffAlignProps = (VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT*)next;
|
||||
// Save the 'next' pointer; we'll unintentionally overwrite it
|
||||
// on the next line. Put it back when we're done.
|
||||
void* savedNext = texelBuffAlignProps->pNext;
|
||||
*texelBuffAlignProps = _texelBuffAlignProperties;
|
||||
texelBuffAlignProps->pNext = savedNext;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
|
||||
auto* divisorProps = (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*)next;
|
||||
divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32;
|
||||
next = (MVKVkAPIStructHeader*)divisorProps->pNext;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_EXTX: {
|
||||
auto* portabilityProps = (VkPhysicalDevicePortabilitySubsetPropertiesEXTX*)next;
|
||||
portabilityProps->minVertexInputBindingStrideAlignment = 4;
|
||||
next = (MVKVkAPIStructHeader*)portabilityProps->pNext;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
next = (MVKVkAPIStructHeader*)next->pNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1113,14 +1118,86 @@ void MVKPhysicalDevice::initProperties() {
|
||||
_properties.limits.bufferImageGranularity = _metalFeatures.mtlBufferAlignment;
|
||||
_properties.limits.nonCoherentAtomSize = _metalFeatures.mtlBufferAlignment;
|
||||
|
||||
if ([_mtlDevice respondsToSelector: @selector(minimumLinearTextureAlignmentForPixelFormat:)]) {
|
||||
// Figure out the greatest alignment required by all supported formats, and
|
||||
// whether or not they only require alignment to a single texel. We'll use this
|
||||
// information to fill out the VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT
|
||||
// struct.
|
||||
uint32_t maxStorage = 0, maxUniform = 0;
|
||||
bool singleTexelStorage = true, singleTexelUniform = true;
|
||||
mvkEnumerateSupportedFormats({0, 0, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT}, true, [&](VkFormat vk) {
|
||||
NSUInteger alignment;
|
||||
if ([_mtlDevice respondsToSelector: @selector(minimumTextureBufferAlignmentForPixelFormat:)]) {
|
||||
alignment = [_mtlDevice minimumTextureBufferAlignmentForPixelFormat: mvkMTLPixelFormatFromVkFormat(vk)];
|
||||
} else {
|
||||
alignment = [_mtlDevice minimumLinearTextureAlignmentForPixelFormat: mvkMTLPixelFormatFromVkFormat(vk)];
|
||||
}
|
||||
VkFormatProperties props = mvkVkFormatProperties(vk, getFormatIsSupported(vk));
|
||||
// For uncompressed formats, this is the size of a single texel.
|
||||
// Note that no implementations of Metal support compressed formats
|
||||
// in a linear texture (including texture buffers). It's likely that even
|
||||
// if they did, this would be the absolute minimum alignment.
|
||||
uint32_t texelSize = mvkVkFormatBytesPerBlock(vk);
|
||||
// From the spec:
|
||||
// "If the size of a single texel is a multiple of three bytes, then
|
||||
// the size of a single component of the format is used instead."
|
||||
if (texelSize % 3 == 0) {
|
||||
switch (mvkFormatTypeFromVkFormat(vk)) {
|
||||
case kMVKFormatColorInt8:
|
||||
case kMVKFormatColorUInt8:
|
||||
texelSize = 1;
|
||||
break;
|
||||
case kMVKFormatColorHalf:
|
||||
case kMVKFormatColorInt16:
|
||||
case kMVKFormatColorUInt16:
|
||||
texelSize = 2;
|
||||
break;
|
||||
case kMVKFormatColorFloat:
|
||||
case kMVKFormatColorInt32:
|
||||
case kMVKFormatColorUInt32:
|
||||
default:
|
||||
texelSize = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mvkAreAllFlagsEnabled(props.bufferFeatures, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)) {
|
||||
maxStorage = max(maxStorage, uint32_t(alignment));
|
||||
if (alignment % texelSize != 0) { singleTexelStorage = false; }
|
||||
}
|
||||
if (mvkAreAllFlagsEnabled(props.bufferFeatures, VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)) {
|
||||
maxUniform = max(maxUniform, uint32_t(alignment));
|
||||
if (alignment % texelSize != 0) { singleTexelUniform = false; }
|
||||
}
|
||||
return true;
|
||||
});
|
||||
_texelBuffAlignProperties.storageTexelBufferOffsetAlignmentBytes = maxStorage;
|
||||
_texelBuffAlignProperties.storageTexelBufferOffsetSingleTexelAlignment = singleTexelStorage;
|
||||
_texelBuffAlignProperties.uniformTexelBufferOffsetAlignmentBytes = maxUniform;
|
||||
_texelBuffAlignProperties.uniformTexelBufferOffsetSingleTexelAlignment = singleTexelUniform;
|
||||
_properties.limits.minTexelBufferOffsetAlignment = max(maxStorage, maxUniform);
|
||||
} else {
|
||||
#if MVK_IOS
|
||||
if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1]) {
|
||||
_properties.limits.minTexelBufferOffsetAlignment = 16;
|
||||
} else {
|
||||
_properties.limits.minTexelBufferOffsetAlignment = 64;
|
||||
}
|
||||
#endif
|
||||
#if MVK_MACOS
|
||||
_properties.limits.minTexelBufferOffsetAlignment = 256;
|
||||
#endif
|
||||
_texelBuffAlignProperties.storageTexelBufferOffsetAlignmentBytes = _properties.limits.minTexelBufferOffsetAlignment;
|
||||
_texelBuffAlignProperties.storageTexelBufferOffsetSingleTexelAlignment = VK_FALSE;
|
||||
_texelBuffAlignProperties.uniformTexelBufferOffsetAlignmentBytes = _properties.limits.minTexelBufferOffsetAlignment;
|
||||
_texelBuffAlignProperties.uniformTexelBufferOffsetSingleTexelAlignment = VK_FALSE;
|
||||
}
|
||||
|
||||
#if MVK_IOS
|
||||
_properties.limits.maxFragmentInputComponents = 60;
|
||||
|
||||
if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1]) {
|
||||
_properties.limits.minTexelBufferOffsetAlignment = 16;
|
||||
_properties.limits.optimalBufferCopyOffsetAlignment = 16;
|
||||
} else {
|
||||
_properties.limits.minTexelBufferOffsetAlignment = 64;
|
||||
_properties.limits.optimalBufferCopyOffsetAlignment = 64;
|
||||
}
|
||||
|
||||
@ -1137,7 +1214,6 @@ void MVKPhysicalDevice::initProperties() {
|
||||
#endif
|
||||
#if MVK_MACOS
|
||||
_properties.limits.maxFragmentInputComponents = 128;
|
||||
_properties.limits.minTexelBufferOffsetAlignment = 256;
|
||||
_properties.limits.optimalBufferCopyOffsetAlignment = 256;
|
||||
|
||||
if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily1_v2]) {
|
||||
|
@ -62,6 +62,7 @@ MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE)
|
||||
MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT)
|
||||
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
|
||||
MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE)
|
||||
MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT)
|
||||
MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR)
|
||||
MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET)
|
||||
MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE)
|
||||
|
@ -53,6 +53,9 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
|
||||
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
|
||||
return mvkOSVersion() >= 10.14;
|
||||
}
|
||||
if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) {
|
||||
return mvkOSVersion() >= 10.13;
|
||||
}
|
||||
if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
|
||||
if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
|
||||
#endif
|
||||
@ -65,6 +68,9 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
|
||||
return mvkOSVersion() >= 12.0;
|
||||
}
|
||||
if (pProperties == &kVkExtProps_EXT_SWAPCHAIN_COLOR_SPACE) { return false; }
|
||||
if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) {
|
||||
return mvkOSVersion() >= 11.0;
|
||||
}
|
||||
if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
|
||||
#endif
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include "mvk_datatypes.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
class MVKBaseObject;
|
||||
|
||||
/*
|
||||
@ -75,4 +77,13 @@ MTLWinding mvkMTLWindingFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObjec
|
||||
MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj);
|
||||
#define mvkMTLTessellationPartitionModeFromSpvExecutionMode(spvMode) mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(spvMode, this)
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Image properties
|
||||
|
||||
#pragma mark Texture formats
|
||||
|
||||
/** Enumerates all formats that support the given features, calling a specified function for each one. */
|
||||
void mvkEnumerateSupportedFormats(VkFormatProperties properties, bool any, std::function<bool(VkFormat)> func);
|
||||
|
||||
#endif
|
||||
|
@ -665,6 +665,25 @@ MVK_PUBLIC_SYMBOL const char* mvkMTLPixelFormatName(MTLPixelFormat mtlFormat) {
|
||||
return formatDescForMTLPixelFormat(mtlFormat).mtlName;
|
||||
}
|
||||
|
||||
void mvkEnumerateSupportedFormats(VkFormatProperties properties, bool any, std::function<bool(VkFormat)> func) {
|
||||
static const auto areFeaturesSupported = [any](uint32_t a, uint32_t b) {
|
||||
if (any)
|
||||
return mvkIsAnyFlagEnabled(a, b);
|
||||
else
|
||||
return mvkAreAllFlagsEnabled(a, b);
|
||||
};
|
||||
for (auto& formatDesc : _formatDescriptions) {
|
||||
if (formatDesc.isSupported() &&
|
||||
areFeaturesSupported(formatDesc.properties.linearTilingFeatures, properties.linearTilingFeatures) &&
|
||||
areFeaturesSupported(formatDesc.properties.optimalTilingFeatures, properties.optimalTilingFeatures) &&
|
||||
areFeaturesSupported(formatDesc.properties.bufferFeatures, properties.bufferFeatures)) {
|
||||
if (!func(formatDesc.vk)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef mvkMTLVertexFormatFromVkFormat
|
||||
MVK_PUBLIC_SYMBOL MTLVertexFormat mvkMTLVertexFormatFromVkFormat(VkFormat vkFormat) {
|
||||
return mvkMTLVertexFormatFromVkFormatInObj(vkFormat, nullptr);
|
||||
|
Loading…
x
Reference in New Issue
Block a user