Ensure vkGetPhysicalDeviceFormatProperties() are zerod for unsupported VkFormats.
Support MTLPixelFormats with larger values.
MVKPixelFormats::getVkFormatProperties() return
reference and log error if unsupported VkFormat.
Remove tests for null format name strings.
Consolidate MVKPhysicalDevice::getFormatProperties() overloads.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index aa16543..6bdaa3f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -271,7 +271,7 @@
void MVKPhysicalDevice::getFormatProperties(VkFormat format, VkFormatProperties2KHR* pFormatProperties) {
pFormatProperties->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR;
- pFormatProperties->formatProperties = _pixelFormats.getVkFormatProperties(format);
+ getFormatProperties(format, &pFormatProperties->formatProperties);
}
VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format,
@@ -1307,7 +1307,7 @@
} else {
alignment = [_mtlDevice minimumLinearTextureAlignmentForPixelFormat: mtlFmt];
}
- VkFormatProperties props = _pixelFormats.getVkFormatProperties(vk);
+ VkFormatProperties& props = _pixelFormats.getVkFormatProperties(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
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
index 9e2c4a1..7e124f1 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.h
@@ -31,7 +31,8 @@
// Validate these values periodically as new formats are added over time.
static const uint32_t _vkFormatCount = 256;
static const uint32_t _vkFormatCoreCount = VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1;
-static const uint32_t _mtlPixelFormatCount = MTLPixelFormatX32_Stencil8 + 2; // The actual last enum value is not available on iOS
+static const uint32_t _mtlPixelFormatCount = 128;
+static const uint32_t _mtlPixelFormatCoreCount = MTLPixelFormatX32_Stencil8 + 2; // The actual last enum value is not available on iOS
static const uint32_t _mtlVertexFormatCount = MTLVertexFormatHalf + 1;
@@ -233,7 +234,7 @@
size_t getBytesPerLayer(MTLPixelFormat mtlFormat, size_t bytesPerRow, uint32_t texelRowsPerLayer);
/** Returns the default properties for the specified Vulkan format. */
- VkFormatProperties getVkFormatProperties(VkFormat vkFormat);
+ VkFormatProperties& getVkFormatProperties(VkFormat vkFormat);
/** Returns the Metal format capabilities supported by the specified Vulkan format. */
MVKMTLFmtCaps getCapabilities(VkFormat vkFormat);
@@ -323,7 +324,10 @@
uint16_t _vkFormatDescIndicesByVkFormatsCore[_vkFormatCoreCount];
std::unordered_map<uint32_t, uint32_t> _vkFormatDescIndicesByVkFormatsExt;
- // Metal formats have small values and are mapped by simple lookup array.
- uint16_t _mtlFormatDescIndicesByMTLPixelFormats[_mtlPixelFormatCount];
+ // Most Metal formats have small values and are mapped by simple lookup array.
+ // Outliers are mapped by a map.
+ uint16_t _mtlFormatDescIndicesByMTLPixelFormatsCore[_mtlPixelFormatCoreCount];
+ std::unordered_map<NSUInteger, uint32_t> _mtlFormatDescIndicesByMTLPixelFormatsExt;
+
uint16_t _mtlFormatDescIndicesByMTLVertexFormats[_mtlVertexFormatCount];
};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index c307579..361358c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -198,7 +198,7 @@
if ( !mtlPixFmt || !vkDesc.hasReportedSubstitution ) {
string errMsg;
errMsg += "VkFormat ";
- errMsg += (vkDesc.name) ? vkDesc.name : to_string(vkDesc.vkFormat);
+ errMsg += vkDesc.name;
errMsg += " is not supported on this device.";
if (mtlPixFmt) {
@@ -206,7 +206,7 @@
auto& vkDescSubs = getVkFormatDesc(mtlPixFmt);
errMsg += " Using VkFormat ";
- errMsg += (vkDescSubs.name) ? vkDescSubs.name : to_string(vkDescSubs.vkFormat);
+ errMsg += vkDescSubs.name;
errMsg += " instead.";
}
MVKBaseObject::reportError(_physicalDevice, VK_ERROR_FORMAT_NOT_SUPPORTED, "%s", errMsg.c_str());
@@ -262,8 +262,13 @@
return mvkCeilingDivide(texelRowsPerLayer, getVkFormatDesc(mtlFormat).blockTexelSize.height) * bytesPerRow;
}
-VkFormatProperties MVKPixelFormats::getVkFormatProperties(VkFormat vkFormat) {
- return getVkFormatDesc(vkFormat).properties;
+VkFormatProperties& MVKPixelFormats::getVkFormatProperties(VkFormat vkFormat) {
+ auto& vkDesc = getVkFormatDesc(vkFormat);
+ if ( !vkDesc.isSupported() ) {
+ MVKBaseObject::reportError(_physicalDevice, VK_ERROR_FORMAT_NOT_SUPPORTED,
+ "VkFormat %s is not supported on this device.", vkDesc.name);
+ }
+ return vkDesc.properties;
}
MVKMTLFmtCaps MVKPixelFormats::getCapabilities(VkFormat vkFormat) {
@@ -311,7 +316,7 @@
if ( !mtlVtxFmt && vkFormat ) {
string errMsg;
errMsg += "VkFormat ";
- errMsg += (vkDesc.name) ? vkDesc.name : to_string(vkDesc.vkFormat);
+ errMsg += vkDesc.name;
errMsg += " is not supported for vertex buffers on this device.";
if (vkDesc.vertexIsSupportedOrSubstitutable()) {
@@ -319,7 +324,7 @@
auto& vkDescSubs = getVkFormatDesc(getMTLVertexFormatDesc(mtlVtxFmt).vkFormat);
errMsg += " Using VkFormat ";
- errMsg += (vkDescSubs.name) ? vkDescSubs.name : to_string(vkDescSubs.vkFormat);
+ errMsg += vkDescSubs.name;
errMsg += " instead.";
}
MVKBaseObject::reportError(_physicalDevice, VK_ERROR_FORMAT_NOT_SUPPORTED, "%s", errMsg.c_str());
@@ -449,7 +454,9 @@
// Return a reference to the Vulkan format descriptor corresponding to the VkFormat.
MVKVkFormatDesc& MVKPixelFormats::getVkFormatDesc(VkFormat vkFormat) {
- uint16_t fmtIdx = (vkFormat < _vkFormatCoreCount) ? _vkFormatDescIndicesByVkFormatsCore[vkFormat] : _vkFormatDescIndicesByVkFormatsExt[vkFormat];
+ uint16_t fmtIdx = ((vkFormat < _vkFormatCoreCount)
+ ? _vkFormatDescIndicesByVkFormatsCore[vkFormat]
+ : _vkFormatDescIndicesByVkFormatsExt[vkFormat]);
return _vkFormatDescriptions[fmtIdx];
}
@@ -465,7 +472,9 @@
// Return a reference to the Metal format descriptor corresponding to the MTLPixelFormat.
MVKMTLFormatDesc& MVKPixelFormats::getMTLPixelFormatDesc(MTLPixelFormat mtlFormat) {
- uint16_t fmtIdx = (mtlFormat < _mtlPixelFormatCount) ? _mtlFormatDescIndicesByMTLPixelFormats[mtlFormat] : 0;
+ uint16_t fmtIdx = ((mtlFormat < _mtlPixelFormatCoreCount)
+ ? _mtlFormatDescIndicesByMTLPixelFormatsCore[mtlFormat]
+ : _mtlFormatDescIndicesByMTLPixelFormatsExt[mtlFormat]);
return _mtlPixelFormatDescriptions[fmtIdx];
}
@@ -510,6 +519,7 @@
uint32_t fmtIdx = 0;
// When adding to this list, be sure to ensure _vkFormatCount is large enough for the format count
+
// UNDEFINED must come first.
addVkFormatDesc( UNDEFINED, Invalid, Invalid, Invalid, Invalid, 1, 1, 0, None );
@@ -939,6 +949,7 @@
uint32_t fmtIdx = 0;
// When adding to this list, be sure to ensure _mtlVertexFormatCount is large enough for the format count
+
// MTLVertexFormatInvalid must come first.
addMTLVertexFormatDesc( Invalid, None, None );
@@ -1014,13 +1025,21 @@
void MVKPixelFormats::buildMTLFormatMaps() {
// Set all MTLPixelFormats and MTLVertexFormats to undefined/invalid
- mvkClear(_mtlFormatDescIndicesByMTLPixelFormats, _mtlPixelFormatCount);
+ mvkClear(_mtlFormatDescIndicesByMTLPixelFormatsCore, _mtlPixelFormatCoreCount);
mvkClear(_mtlFormatDescIndicesByMTLVertexFormats, _mtlVertexFormatCount);
- // Build lookup table for MTLPixelFormat specs
+ // Build lookup table for MTLPixelFormat specs.
+ // For most Metal format values, which are small and consecutive, use a simple lookup array.
+ // For outlier format values, which can be large, use a map.
for (uint32_t fmtIdx = 0; fmtIdx < _mtlPixelFormatCount; fmtIdx++) {
MTLPixelFormat fmt = _mtlPixelFormatDescriptions[fmtIdx].mtlPixelFormat;
- if (fmt) { _mtlFormatDescIndicesByMTLPixelFormats[fmt] = fmtIdx; }
+ if (fmt) {
+ if (fmt < _mtlPixelFormatCoreCount) {
+ _mtlFormatDescIndicesByMTLPixelFormatsCore[fmt] = fmtIdx;
+ } else {
+ _mtlFormatDescIndicesByMTLPixelFormatsExt[fmt] = fmtIdx;
+ }
+ }
}
// Build lookup table for MTLVertexFormat specs