Reduce memory used by MVKPixelFormats lookups.
- Add MVKInflectionMap collection to manage lookups based on enums that have a large set of consecutive elements, plus additional enum values that are more sparsely assigned. - Recognize every MTLPixelFormat value can be held in uint16_t. - Reduce inflection-map sizes by calling shrink_to_fit(). - runcts script log completion time (unrelated).
This commit is contained in:
parent
fe65485bfb
commit
88799cf255
@ -318,6 +318,10 @@
|
||||
A9A5E9C725C0822700E9085E /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; };
|
||||
A9A5E9C825C0822700E9085E /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; };
|
||||
A9A5E9C925C0822700E9085E /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; };
|
||||
A9AB952B2B3EDFCC00C4E967 /* MVKInflectionMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A9AB95292B3EDFCC00C4E967 /* MVKInflectionMap.h */; };
|
||||
A9AB952C2B3EDFCC00C4E967 /* MVKInflectionMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A9AB95292B3EDFCC00C4E967 /* MVKInflectionMap.h */; };
|
||||
A9AB952D2B3EDFCC00C4E967 /* MVKInflectionMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A9AB95292B3EDFCC00C4E967 /* MVKInflectionMap.h */; };
|
||||
A9AB952E2B3EDFCC00C4E967 /* MVKInflectionMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A9AB95292B3EDFCC00C4E967 /* MVKInflectionMap.h */; };
|
||||
A9B3D73B29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */; };
|
||||
A9B3D73C29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */; };
|
||||
A9B3D73D29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */; };
|
||||
@ -667,6 +671,7 @@
|
||||
A99C91002295FAC500A061DA /* MVKVulkanAPIObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKVulkanAPIObject.mm; sourceTree = "<group>"; };
|
||||
A99C91012295FAC500A061DA /* MVKVulkanAPIObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKVulkanAPIObject.h; sourceTree = "<group>"; };
|
||||
A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKEnvironment.cpp; sourceTree = "<group>"; };
|
||||
A9AB95292B3EDFCC00C4E967 /* MVKInflectionMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKInflectionMap.h; sourceTree = "<group>"; };
|
||||
A9AD67C72054DD6C00ED3C08 /* vulkan */ = {isa = PBXFileReference; lastKnownFileType = folder; path = vulkan; sourceTree = "<group>"; };
|
||||
A9B3D73829F9B3B100745CD4 /* mvk_deprecated_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mvk_deprecated_api.h; sourceTree = "<group>"; };
|
||||
A9B3D73A29F9B3B100745CD4 /* mvk_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mvk_config.h; sourceTree = "<group>"; };
|
||||
@ -840,7 +845,6 @@
|
||||
A98149401FB6A3F7005F00B4 /* Utility */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A9F0429E1FB4CF82009FCCB8 /* MVKLogging.h */,
|
||||
A98149421FB6A3F7005F00B4 /* MVKBaseObject.h */,
|
||||
A98149411FB6A3F7005F00B4 /* MVKBaseObject.mm */,
|
||||
A9D7104E25CDE05E00E38106 /* MVKBitArray.h */,
|
||||
@ -854,6 +858,8 @@
|
||||
A98149431FB6A3F7005F00B4 /* MVKEnvironment.h */,
|
||||
A98149451FB6A3F7005F00B4 /* MVKFoundation.cpp */,
|
||||
A98149441FB6A3F7005F00B4 /* MVKFoundation.h */,
|
||||
A9AB95292B3EDFCC00C4E967 /* MVKInflectionMap.h */,
|
||||
A9F0429E1FB4CF82009FCCB8 /* MVKLogging.h */,
|
||||
A98149461FB6A3F7005F00B4 /* MVKObjectPool.h */,
|
||||
A9F3D9DB24732A4D00745190 /* MVKSmallVector.h */,
|
||||
A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */,
|
||||
@ -981,6 +987,7 @@
|
||||
2FEA0A5924902F9F00EEF3AD /* MVKDevice.h in Headers */,
|
||||
2FEA0A5A24902F9F00EEF3AD /* MVKSmallVector.h in Headers */,
|
||||
2FEA0A5C24902F9F00EEF3AD /* MVKCommandPool.h in Headers */,
|
||||
A9AB952C2B3EDFCC00C4E967 /* MVKInflectionMap.h in Headers */,
|
||||
A9B3D74329F9BDEE00745CD4 /* mvk_private_api.h in Headers */,
|
||||
2FEA0A5D24902F9F00EEF3AD /* MVKShaderModule.h in Headers */,
|
||||
2FEA0A5E24902F9F00EEF3AD /* MVKVulkanAPIObject.h in Headers */,
|
||||
@ -1060,6 +1067,7 @@
|
||||
A9F3D9DE24732A4D00745190 /* MVKSmallVector.h in Headers */,
|
||||
A94FB7D41C7DFB4800632CA3 /* MVKCommandPool.h in Headers */,
|
||||
A94FB80C1C7DFB4800632CA3 /* MVKShaderModule.h in Headers */,
|
||||
A9AB952B2B3EDFCC00C4E967 /* MVKInflectionMap.h in Headers */,
|
||||
A99C91042295FAC600A061DA /* MVKVulkanAPIObject.h in Headers */,
|
||||
A94FB7C01C7DFB4800632CA3 /* MVKCmdQueries.h in Headers */,
|
||||
A9B3D73B29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */,
|
||||
@ -1138,6 +1146,7 @@
|
||||
A94FB7D51C7DFB4800632CA3 /* MVKCommandPool.h in Headers */,
|
||||
A94FB80D1C7DFB4800632CA3 /* MVKShaderModule.h in Headers */,
|
||||
A99C91052295FAC600A061DA /* MVKVulkanAPIObject.h in Headers */,
|
||||
A9AB952D2B3EDFCC00C4E967 /* MVKInflectionMap.h in Headers */,
|
||||
A94FB7C11C7DFB4800632CA3 /* MVKCmdQueries.h in Headers */,
|
||||
A94FB7CD1C7DFB4800632CA3 /* MVKCommand.h in Headers */,
|
||||
A9B3D73D29F9B3B100745CD4 /* mvk_deprecated_api.h in Headers */,
|
||||
@ -1237,6 +1246,7 @@
|
||||
DCFD7F142A45BC6E007BBBF7 /* MVKCmdTransfer.h in Headers */,
|
||||
DCFD7F152A45BC6E007BBBF7 /* MVKDescriptor.h in Headers */,
|
||||
DCFD7F162A45BC6E007BBBF7 /* MVKCmdDraw.h in Headers */,
|
||||
A9AB952E2B3EDFCC00C4E967 /* MVKInflectionMap.h in Headers */,
|
||||
DCFD7F172A45BC6E007BBBF7 /* MVKCommandBuffer.h in Headers */,
|
||||
DCFD7F182A45BC6E007BBBF7 /* MTLRenderPassDescriptor+MoltenVK.h in Headers */,
|
||||
DCFD7F192A45BC6E007BBBF7 /* MVKCmdDebug.h in Headers */,
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "MVKBaseObject.h"
|
||||
#include "MVKOSExtensions.h"
|
||||
#include "MVKInflectionMap.h"
|
||||
#include "mvk_datatypes.hpp"
|
||||
#include <spirv_msl.hpp>
|
||||
#include <unordered_map>
|
||||
@ -29,14 +30,6 @@
|
||||
class MVKPhysicalDevice;
|
||||
|
||||
|
||||
// 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 = 256;
|
||||
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;
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Metal format capabilities
|
||||
|
||||
@ -418,7 +411,6 @@ protected:
|
||||
void initVkFormatCapabilities();
|
||||
void initMTLPixelFormatCapabilities();
|
||||
void initMTLVertexFormatCapabilities();
|
||||
void buildMTLFormatMaps();
|
||||
void buildVkFormatMaps();
|
||||
void setFormatProperties(MVKVkFormatDesc& vkDesc);
|
||||
void modifyMTLFormatCapabilities();
|
||||
@ -446,17 +438,7 @@ protected:
|
||||
MVKMTLFmtCaps mtlFmtCaps);
|
||||
|
||||
MVKPhysicalDevice* _physicalDevice;
|
||||
MVKVkFormatDesc _vkFormatDescriptions[_vkFormatCount];
|
||||
MVKMTLFormatDesc _mtlPixelFormatDescriptions[_mtlPixelFormatCount];
|
||||
MVKMTLFormatDesc _mtlVertexFormatDescriptions[_mtlVertexFormatCount];
|
||||
|
||||
// Vulkan core formats have small values and are mapped by simple lookup array.
|
||||
// Vulkan extension formats have larger values and are mapped by a map.
|
||||
uint16_t _vkFormatDescIndicesByVkFormatsCore[_vkFormatCoreCount];
|
||||
std::unordered_map<uint32_t, uint32_t> _vkFormatDescIndicesByVkFormatsExt;
|
||||
|
||||
// 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;
|
||||
MVKInflectionMap<VkFormat, MVKVkFormatDesc, VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1> _vkFormatDescriptions;
|
||||
MVKInflectionMap<uint16_t, MVKMTLFormatDesc, MTLPixelFormatX32_Stencil8 + 2> _mtlPixelFormatDescriptions; // The actual last enum value is not available on iOS
|
||||
MVKSmallVector<MVKMTLFormatDesc> _mtlVertexFormatDescriptions;
|
||||
};
|
||||
|
@ -762,10 +762,7 @@ MTLTextureUsage MVKPixelFormats::getMTLTextureUsage(VkImageUsageFlags vkImageUsa
|
||||
|
||||
// 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]);
|
||||
return _vkFormatDescriptions[fmtIdx];
|
||||
return _vkFormatDescriptions[vkFormat];
|
||||
}
|
||||
|
||||
// Return a reference to the Vulkan format descriptor corresponding to the MTLPixelFormat.
|
||||
@ -775,15 +772,12 @@ MVKVkFormatDesc& MVKPixelFormats::getVkFormatDesc(MTLPixelFormat mtlFormat) {
|
||||
|
||||
// Return a reference to the Metal format descriptor corresponding to the MTLPixelFormat.
|
||||
MVKMTLFormatDesc& MVKPixelFormats::getMTLPixelFormatDesc(MTLPixelFormat mtlFormat) {
|
||||
uint16_t fmtIdx = ((mtlFormat < _mtlPixelFormatCoreCount)
|
||||
? _mtlFormatDescIndicesByMTLPixelFormatsCore[mtlFormat]
|
||||
: _mtlFormatDescIndicesByMTLPixelFormatsExt[mtlFormat]);
|
||||
return _mtlPixelFormatDescriptions[fmtIdx];
|
||||
return _mtlPixelFormatDescriptions[mtlFormat];
|
||||
}
|
||||
|
||||
// Return a reference to the Metal format descriptor corresponding to the MTLVertexFormat.
|
||||
MVKMTLFormatDesc& MVKPixelFormats::getMTLVertexFormatDesc(MTLVertexFormat mtlFormat) {
|
||||
return _mtlVertexFormatDescriptions[mtlFormat < _mtlVertexFormatCount ? mtlFormat : 0];
|
||||
return _mtlVertexFormatDescriptions[mtlFormat];
|
||||
}
|
||||
|
||||
|
||||
@ -794,7 +788,6 @@ MVKPixelFormats::MVKPixelFormats(MVKPhysicalDevice* physicalDevice) : _physicalD
|
||||
// Build and update the Metal formats
|
||||
initMTLPixelFormatCapabilities();
|
||||
initMTLVertexFormatCapabilities();
|
||||
buildMTLFormatMaps();
|
||||
modifyMTLFormatCapabilities();
|
||||
|
||||
// Build the Vulkan formats and link them to the Metal formats
|
||||
@ -803,11 +796,11 @@ MVKPixelFormats::MVKPixelFormats(MVKPhysicalDevice* physicalDevice) : _physicalD
|
||||
}
|
||||
|
||||
#define addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE, SWIZ_R, SWIZ_G, SWIZ_B, SWIZ_A) \
|
||||
MVKAssert(fmtIdx < _vkFormatCount, "Attempting to describe %d VkFormats, but only have space for %d. Increase the value of _vkFormatCount", fmtIdx + 1, _vkFormatCount); \
|
||||
_vkFormatDescriptions[fmtIdx++] = { VK_FORMAT_ ##VK_FMT, MTLPixelFormat ##MTL_FMT, MTLPixelFormat ##MTL_FMT_ALT, MTLVertexFormat ##MTL_VTX_FMT, MTLVertexFormat ##MTL_VTX_FMT_ALT, \
|
||||
CSPC, CSCB, { BLK_W, BLK_H }, BLK_BYTE_CNT, kMVKFormat ##MVK_FMT_TYPE, { 0, 0, 0 }, \
|
||||
{ VK_COMPONENT_SWIZZLE_ ##SWIZ_R, VK_COMPONENT_SWIZZLE_ ##SWIZ_G, VK_COMPONENT_SWIZZLE_ ##SWIZ_B, VK_COMPONENT_SWIZZLE_ ##SWIZ_A }, \
|
||||
"VK_FORMAT_" #VK_FMT, false }
|
||||
vkFmt = VK_FORMAT_ ##VK_FMT; \
|
||||
_vkFormatDescriptions[vkFmt] = { vkFmt, MTLPixelFormat ##MTL_FMT, MTLPixelFormat ##MTL_FMT_ALT, MTLVertexFormat ##MTL_VTX_FMT, MTLVertexFormat ##MTL_VTX_FMT_ALT, \
|
||||
CSPC, CSCB, { BLK_W, BLK_H }, BLK_BYTE_CNT, kMVKFormat ##MVK_FMT_TYPE, { 0, 0, 0 }, \
|
||||
{ VK_COMPONENT_SWIZZLE_ ##SWIZ_R, VK_COMPONENT_SWIZZLE_ ##SWIZ_G, VK_COMPONENT_SWIZZLE_ ##SWIZ_B, VK_COMPONENT_SWIZZLE_ ##SWIZ_A }, \
|
||||
"VK_FORMAT_" #VK_FMT, false }
|
||||
|
||||
#define addVkFormatDesc(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE) \
|
||||
addVkFormatDescFull(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, 0, 0, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE, IDENTITY, IDENTITY, IDENTITY, IDENTITY)
|
||||
@ -819,12 +812,7 @@ MVKPixelFormats::MVKPixelFormats(MVKPhysicalDevice* physicalDevice) : _physicalD
|
||||
addVkFormatDescFull(VK_FMT, MTL_FMT, Invalid, Invalid, Invalid, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, ColorFloat, IDENTITY, IDENTITY, IDENTITY, IDENTITY)
|
||||
|
||||
void MVKPixelFormats::initVkFormatCapabilities() {
|
||||
|
||||
mvkClear(_vkFormatDescriptions, _vkFormatCount);
|
||||
|
||||
uint32_t fmtIdx = 0;
|
||||
|
||||
// When adding to this list, be sure to ensure _vkFormatCount is large enough for the format count
|
||||
VkFormat vkFmt;
|
||||
|
||||
// UNDEFINED must come first.
|
||||
addVkFormatDesc( UNDEFINED, Invalid, Invalid, Invalid, Invalid, 1, 1, 0, None );
|
||||
@ -1115,15 +1103,14 @@ void MVKPixelFormats::initVkFormatCapabilities() {
|
||||
addVkFormatDescChromaSubsampling( G16_B16R16_2PLANE_422_UNORM, Invalid, 2, 16, 2, 1, 8 );
|
||||
addVkFormatDescChromaSubsampling( G16_B16_R16_3PLANE_444_UNORM, Invalid, 3, 16, 1, 1, 6 );
|
||||
|
||||
// When adding to this list, be sure to ensure _vkFormatCount is large enough for the format count
|
||||
_vkFormatDescriptions.shrink_to_fit();
|
||||
}
|
||||
|
||||
|
||||
#define addMTLPixelFormatDescFull(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS, MTL_FMT_LINEAR) \
|
||||
MVKAssert(fmtIdx < _mtlPixelFormatCount, "Attempting to describe %d MTLPixelFormats, but only have space for %d. Increase the value of _mtlPixelFormatCount", fmtIdx + 1, _mtlPixelFormatCount); \
|
||||
_mtlPixelFormatDescriptions[fmtIdx++] = { .mtlPixelFormat = MTLPixelFormat ##MTL_FMT, VK_FORMAT_UNDEFINED, \
|
||||
mvkSelectPlatformValue<MVKMTLFmtCaps>(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS), \
|
||||
MVKMTLViewClass:: VIEW_CLASS, MTLPixelFormat ##MTL_FMT_LINEAR, "MTLPixelFormat" #MTL_FMT }
|
||||
mtlPixFmt = MTLPixelFormat ##MTL_FMT; \
|
||||
_mtlPixelFormatDescriptions[mtlPixFmt] = { .mtlPixelFormat = mtlPixFmt, VK_FORMAT_UNDEFINED, \
|
||||
mvkSelectPlatformValue<MVKMTLFmtCaps>(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS), \
|
||||
MVKMTLViewClass:: VIEW_CLASS, MTLPixelFormat ##MTL_FMT_LINEAR, "MTLPixelFormat" #MTL_FMT }
|
||||
|
||||
#define addMTLPixelFormatDesc(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS) \
|
||||
addMTLPixelFormatDescFull(MTL_FMT, VIEW_CLASS, IOS_CAPS, MACOS_CAPS, MTL_FMT)
|
||||
@ -1133,12 +1120,7 @@ void MVKPixelFormats::initVkFormatCapabilities() {
|
||||
|
||||
|
||||
void MVKPixelFormats::initMTLPixelFormatCapabilities() {
|
||||
|
||||
mvkClear(_mtlPixelFormatDescriptions, _mtlPixelFormatCount);
|
||||
|
||||
uint32_t fmtIdx = 0;
|
||||
|
||||
// When adding to this list, be sure to ensure _mtlPixelFormatCount is large enough for the format count
|
||||
MTLPixelFormat mtlPixFmt;
|
||||
|
||||
// MTLPixelFormatInvalid must come first.
|
||||
addMTLPixelFormatDesc ( Invalid, None, None, None );
|
||||
@ -1307,26 +1289,21 @@ void MVKPixelFormats::initMTLPixelFormatCapabilities() {
|
||||
addMTLPixelFormatDesc ( X24_Stencil8, Depth24_Stencil8, None, DRMR );
|
||||
addMTLPixelFormatDesc ( X32_Stencil8, Depth32_Stencil8, DRM, DRMR );
|
||||
|
||||
// When adding to this list, be sure to ensure _mtlPixelFormatCount is large enough for the format count
|
||||
_mtlPixelFormatDescriptions.shrink_to_fit();
|
||||
}
|
||||
|
||||
// If necessary, resize vector with empty elements
|
||||
#define addMTLVertexFormatDesc(MTL_VTX_FMT, IOS_CAPS, MACOS_CAPS) \
|
||||
mtlVtxFmt = MTLVertexFormat ##MTL_VTX_FMT; \
|
||||
if (mtlVtxFmt < _mtlVertexFormatCount) { \
|
||||
_mtlVertexFormatDescriptions[mtlVtxFmt] = { .mtlVertexFormat = mtlVtxFmt, VK_FORMAT_UNDEFINED, \
|
||||
mvkSelectPlatformValue<MVKMTLFmtCaps>(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS), \
|
||||
MVKMTLViewClass::None, MTLPixelFormatInvalid, "MTLVertexFormat" #MTL_VTX_FMT }; \
|
||||
} else { \
|
||||
MVKAssert(false, "Attempting to describe at least %lu MTLVertexFormats, but only have space for %d. Increase the value of _mtlVertexFormatCount", mtlVtxFmt + 1, _mtlVertexFormatCount); \
|
||||
}
|
||||
if (mtlVtxFmt >= _mtlVertexFormatDescriptions.size()) { _mtlVertexFormatDescriptions.resize(mtlVtxFmt + 1, {}); } \
|
||||
_mtlVertexFormatDescriptions[mtlVtxFmt] = { .mtlVertexFormat = mtlVtxFmt, VK_FORMAT_UNDEFINED, \
|
||||
mvkSelectPlatformValue<MVKMTLFmtCaps>(kMVKMTLFmtCaps ##MACOS_CAPS, kMVKMTLFmtCaps ##IOS_CAPS), \
|
||||
MVKMTLViewClass::None, MTLPixelFormatInvalid, "MTLVertexFormat" #MTL_VTX_FMT };
|
||||
|
||||
void MVKPixelFormats::initMTLVertexFormatCapabilities() {
|
||||
MTLVertexFormat mtlVtxFmt;
|
||||
|
||||
mvkClear(_mtlVertexFormatDescriptions, _mtlVertexFormatCount);
|
||||
|
||||
MTLVertexFormat mtlVtxFmt = MTLVertexFormatInvalid;
|
||||
|
||||
// When adding to this list, be sure to ensure _mtlVertexFormatCount is large enough for the format count
|
||||
_mtlVertexFormatDescriptions.reserve(MTLVertexFormatHalf + 3);
|
||||
|
||||
addMTLVertexFormatDesc( Invalid, None, None ); // MTLVertexFormatInvalid must come first.
|
||||
|
||||
@ -1395,28 +1372,7 @@ void MVKPixelFormats::initMTLVertexFormatCapabilities() {
|
||||
|
||||
addMTLVertexFormatDesc( UChar4Normalized_BGRA, None, None );
|
||||
|
||||
// When adding to this list, be sure to ensure _mtlVertexFormatCount is large enough for the format count
|
||||
}
|
||||
|
||||
// Populates the Metal lookup maps
|
||||
void MVKPixelFormats::buildMTLFormatMaps() {
|
||||
|
||||
// Set all MTLPixelFormats lookups to undefined/invalid
|
||||
mvkClear(_mtlFormatDescIndicesByMTLPixelFormatsCore, _mtlPixelFormatCoreCount);
|
||||
|
||||
// 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) {
|
||||
if (fmt < _mtlPixelFormatCoreCount) {
|
||||
_mtlFormatDescIndicesByMTLPixelFormatsCore[fmt] = fmtIdx;
|
||||
} else {
|
||||
_mtlFormatDescIndicesByMTLPixelFormatsExt[fmt] = fmtIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
_mtlVertexFormatDescriptions.shrink_to_fit();
|
||||
}
|
||||
|
||||
// If the device supports the feature set, add additional capabilities to a MTLPixelFormat
|
||||
@ -1985,69 +1941,50 @@ void MVKPixelFormats::modifyMTLFormatCapabilities(id<MTLDevice> mtlDevice) {
|
||||
#undef addFeatSetMTLVtxFmtCaps
|
||||
#undef addGPUOSMTLVtxFmtCaps
|
||||
|
||||
// Populates the VkFormat lookup maps and connects Vulkan and Metal pixel formats to one-another.
|
||||
// Connects Vulkan and Metal pixel formats to one-another.
|
||||
void MVKPixelFormats::buildVkFormatMaps() {
|
||||
|
||||
// Set the VkFormats to undefined/invalid
|
||||
mvkClear(_vkFormatDescIndicesByVkFormatsCore, _vkFormatCoreCount);
|
||||
|
||||
// Iterate through the VkFormat descriptions, populate the lookup maps and back pointers,
|
||||
// and validate the Metal formats for the platform and OS.
|
||||
for (uint32_t fmtIdx = 0; fmtIdx < _vkFormatCount; fmtIdx++) {
|
||||
MVKVkFormatDesc& vkDesc = _vkFormatDescriptions[fmtIdx];
|
||||
VkFormat vkFmt = vkDesc.vkFormat;
|
||||
if (vkFmt) {
|
||||
// Create a lookup between the Vulkan format and an index to the format info.
|
||||
// For core Vulkan format values, which are small and consecutive, use a simple lookup array.
|
||||
// For extension format values, which can be large, use a map.
|
||||
if (vkFmt < _vkFormatCoreCount) {
|
||||
_vkFormatDescIndicesByVkFormatsCore[vkFmt] = fmtIdx;
|
||||
} else {
|
||||
_vkFormatDescIndicesByVkFormatsExt[vkFmt] = fmtIdx;
|
||||
}
|
||||
|
||||
if (vkDesc.needsSwizzle()) {
|
||||
if (_physicalDevice) {
|
||||
id<MTLDevice> mtlDev = _physicalDevice->getMTLDevice();
|
||||
for (auto& vkDesc : _vkFormatDescriptions) {
|
||||
if (vkDesc.needsSwizzle()) {
|
||||
if (_physicalDevice) {
|
||||
id<MTLDevice> mtlDev = _physicalDevice->getMTLDevice();
|
||||
#if MVK_MACCAT
|
||||
bool supportsNativeTextureSwizzle = [mtlDev supportsFamily: MTLGPUFamilyMacCatalyst2];
|
||||
bool supportsNativeTextureSwizzle = [mtlDev supportsFamily: MTLGPUFamilyMacCatalyst2];
|
||||
#elif MVK_MACOS
|
||||
bool supportsNativeTextureSwizzle = mvkOSVersionIsAtLeast(10.15) && [mtlDev supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily2_v1];
|
||||
bool supportsNativeTextureSwizzle = mvkOSVersionIsAtLeast(10.15) && [mtlDev supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily2_v1];
|
||||
#endif
|
||||
#if MVK_IOS || MVK_TVOS
|
||||
bool supportsNativeTextureSwizzle = mtlDev && mvkOSVersionIsAtLeast(13.0);
|
||||
bool supportsNativeTextureSwizzle = mtlDev && mvkOSVersionIsAtLeast(13.0);
|
||||
#endif
|
||||
if (!supportsNativeTextureSwizzle && !getMVKConfig().fullImageViewSwizzle) {
|
||||
vkDesc.mtlPixelFormat = vkDesc.mtlPixelFormatSubstitute = MTLPixelFormatInvalid;
|
||||
}
|
||||
if (!supportsNativeTextureSwizzle && !getMVKConfig().fullImageViewSwizzle) {
|
||||
vkDesc.mtlPixelFormat = vkDesc.mtlPixelFormatSubstitute = MTLPixelFormatInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the back reference from the Metal formats to the Vulkan format.
|
||||
// Validate the corresponding Metal formats for the platform, and clear them
|
||||
// in the Vulkan format if not supported.
|
||||
if (vkDesc.mtlPixelFormat) {
|
||||
auto& mtlDesc = getMTLPixelFormatDesc(vkDesc.mtlPixelFormat);
|
||||
if ( !mtlDesc.vkFormat ) { mtlDesc.vkFormat = vkFmt; }
|
||||
if ( !mtlDesc.isSupported() ) { vkDesc.mtlPixelFormat = MTLPixelFormatInvalid; }
|
||||
}
|
||||
if (vkDesc.mtlPixelFormatSubstitute) {
|
||||
auto& mtlDesc = getMTLPixelFormatDesc(vkDesc.mtlPixelFormatSubstitute);
|
||||
if ( !mtlDesc.isSupported() ) { vkDesc.mtlPixelFormatSubstitute = MTLPixelFormatInvalid; }
|
||||
}
|
||||
if (vkDesc.mtlVertexFormat) {
|
||||
auto& mtlDesc = getMTLVertexFormatDesc(vkDesc.mtlVertexFormat);
|
||||
if ( !mtlDesc.vkFormat ) { mtlDesc.vkFormat = vkFmt; }
|
||||
if ( !mtlDesc.isSupported() ) { vkDesc.mtlVertexFormat = MTLVertexFormatInvalid; }
|
||||
}
|
||||
if (vkDesc.mtlVertexFormatSubstitute) {
|
||||
auto& mtlDesc = getMTLVertexFormatDesc(vkDesc.mtlVertexFormatSubstitute);
|
||||
if ( !mtlDesc.isSupported() ) { vkDesc.mtlVertexFormatSubstitute = MTLVertexFormatInvalid; }
|
||||
}
|
||||
|
||||
// Set Vulkan format properties
|
||||
setFormatProperties(vkDesc);
|
||||
}
|
||||
|
||||
// Populate the back reference from the Metal formats to the Vulkan format.
|
||||
// Validate the corresponding Metal formats for the platform, and clear them
|
||||
// if the Vulkan format if not supported.
|
||||
if (vkDesc.mtlPixelFormat) {
|
||||
auto& mtlDesc = getMTLPixelFormatDesc(vkDesc.mtlPixelFormat);
|
||||
if ( !mtlDesc.vkFormat ) { mtlDesc.vkFormat = vkDesc.vkFormat; }
|
||||
if ( !mtlDesc.isSupported() ) { vkDesc.mtlPixelFormat = MTLPixelFormatInvalid; }
|
||||
}
|
||||
if (vkDesc.mtlPixelFormatSubstitute) {
|
||||
auto& mtlDesc = getMTLPixelFormatDesc(vkDesc.mtlPixelFormatSubstitute);
|
||||
if ( !mtlDesc.isSupported() ) { vkDesc.mtlPixelFormatSubstitute = MTLPixelFormatInvalid; }
|
||||
}
|
||||
if (vkDesc.mtlVertexFormat) {
|
||||
auto& mtlDesc = getMTLVertexFormatDesc(vkDesc.mtlVertexFormat);
|
||||
if ( !mtlDesc.vkFormat ) { mtlDesc.vkFormat = vkDesc.vkFormat; }
|
||||
if ( !mtlDesc.isSupported() ) { vkDesc.mtlVertexFormat = MTLVertexFormatInvalid; }
|
||||
}
|
||||
if (vkDesc.mtlVertexFormatSubstitute) {
|
||||
auto& mtlDesc = getMTLVertexFormatDesc(vkDesc.mtlVertexFormatSubstitute);
|
||||
if ( !mtlDesc.isSupported() ) { vkDesc.mtlVertexFormatSubstitute = MTLVertexFormatInvalid; }
|
||||
}
|
||||
|
||||
// Set Vulkan format properties
|
||||
setFormatProperties(vkDesc);
|
||||
}
|
||||
}
|
||||
|
||||
|
105
MoltenVK/MoltenVK/Utility/MVKInflectionMap.h
Executable file
105
MoltenVK/MoltenVK/Utility/MVKInflectionMap.h
Executable file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* MVKInflectionMap.h
|
||||
*
|
||||
* Copyright (c) 2015-2023 The Brenwill Workshop Ltd. (http://www.brenwill.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MVKSmallVector.h"
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
* An unordered map that splits elements between a fast-access vector of LinearCount consecutively
|
||||
* indexed elements, and a slower-access map holding sparse indexes larger than LinearCount.
|
||||
*
|
||||
* This design can be useful for a collection that is indexed by an enum that has a large
|
||||
* set of consecutive elements, plus additional enum values that are more sparsely assigned.
|
||||
* Examples of these enums are VkFormat and MTLPixelFormat.
|
||||
*
|
||||
* KeyType is used to lookup values, and must be a type that is convertable to an unsigned integer.
|
||||
* ValueType must have an empty constructor (default or otherwise).
|
||||
* IndexType must be a type that is convertable to an unsigned integer (eg. uint8_t...uint64_t),
|
||||
* and which is large enough to represent the number of values in this map.
|
||||
* Iteration can be accomplished as
|
||||
*/
|
||||
template<typename KeyType, typename ValueType, size_t LinearCount, typename IndexType = uint16_t>
|
||||
class MVKInflectionMap {
|
||||
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
class iterator {
|
||||
MVKInflectionMap* map;
|
||||
IndexType index;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = ValueType;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
|
||||
iterator() : map(nullptr), index(0) {}
|
||||
iterator(MVKInflectionMap& m, const IndexType i) : map(&m), index(i) {}
|
||||
|
||||
iterator &operator=( const iterator &it ) {
|
||||
map = it.map;
|
||||
index = it.index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ValueType* operator->() { return &map->_values[index]; }
|
||||
ValueType& operator*() { return map->_values[index]; }
|
||||
operator ValueType*() { return &map->_values[index]; }
|
||||
|
||||
bool operator==(const iterator& it) const { return map == it.map && index == it.index; }
|
||||
bool operator!=(const iterator& it) const { return map != it.map || index != it.index; }
|
||||
|
||||
iterator& operator++() { index++; return *this; }
|
||||
iterator operator++( int ) { auto t = *this; index++; return t; }
|
||||
|
||||
bool is_valid() const { return index < map->_values.size(); }
|
||||
};
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
|
||||
const ValueType& operator[](const KeyType idx) const { return getValue(idx); }
|
||||
ValueType& operator[](const KeyType idx) { return getValue(idx); }
|
||||
|
||||
iterator begin() { return iterator(*this, 0); }
|
||||
iterator end() { return iterator(*this, _values.size()); }
|
||||
|
||||
bool empty() { return _values.size() == 0; }
|
||||
size_t size() { return _values.size(); }
|
||||
void shrink_to_fit() { _values.shrink_to_fit(); }
|
||||
|
||||
protected:
|
||||
static constexpr IndexType kMVKInflectionMapValueMissing = std::numeric_limits<IndexType>::max();
|
||||
typedef struct IndexValue { IndexType value = kMVKInflectionMapValueMissing; } IndexValue;
|
||||
|
||||
// Returns a refrence to the value at the index.
|
||||
// If the index has not been initialized, add an empty element at
|
||||
// the end of the values array, and set the index to its position.
|
||||
ValueType& getValue(KeyType idx) {
|
||||
IndexValue& valIdx = idx < LinearCount ? _linearIndexes[idx] : _inflectionIndexes[idx];
|
||||
if (valIdx.value == kMVKInflectionMapValueMissing) {
|
||||
_values.push_back({});
|
||||
valIdx.value = _values.size() - 1;
|
||||
}
|
||||
return _values[valIdx.value];
|
||||
}
|
||||
|
||||
MVKSmallVector<ValueType> _values;
|
||||
std::unordered_map<KeyType, IndexValue> _inflectionIndexes;
|
||||
IndexValue _linearIndexes[LinearCount];
|
||||
};
|
@ -131,4 +131,4 @@ start_time=${SECONDS}
|
||||
--deqp-caselist-file="${caselist_file}" \
|
||||
&> "${results_file}"
|
||||
|
||||
echo Testing complete in $(($SECONDS - $start_time)) seconds
|
||||
echo Testing complete in $(($SECONDS - $start_time)) seconds at `date +%r`
|
||||
|
Loading…
x
Reference in New Issue
Block a user