Refactor MVKPixelFormat internals.

Split MVKFormatDesc struct into separate MVKVkFormatDesc & MVKMTLFormatDesc structs.
Separate content into Vulkan and Metal format tables.
This commit is contained in:
Bill Hollings 2020-03-17 10:39:49 -04:00
parent 1f74a6f20d
commit bb69a5bfc6
3 changed files with 696 additions and 418 deletions

View File

@ -16,17 +16,8 @@
* limitations under the License.
*/
/*
* This file contains functions for converting between Vulkan and Metal data types.
*
* The functions here are used internally by MoltenVK, and are exposed here
* as a convenience for use elsewhere within applications using MoltenVK.
*/
#pragma once
#include "mvk_datatypes.h"
#include "MVKEnvironment.h"
#include "MVKBaseObject.h"
@ -36,35 +27,47 @@
#import <Metal/Metal.h>
#pragma mark -
#pragma mark MVKFormatDesc
/** Validate these values periodically as new formats are added over time. */
static const uint32_t _vkSpecFormatCount = 256;
static const uint32_t _vkFormatCount = 256;
static const uint32_t _vkFormatCoreCount = VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1;
static const uint32_t _mtlFormatCount = MTLPixelFormatX32_Stencil8 + 2; // The actual last enum value is not available on iOS
static const uint32_t _mtlPixelFormatCount = MTLPixelFormatX32_Stencil8 + 2; // The actual last enum value is not available on iOS
static const uint32_t _mtlVertexFormatCount = MTLVertexFormatHalf + 1;
/** Describes the properties of each VkFormat, including the corresponding Metal pixel format. */
#pragma mark -
#pragma mark Format descriptions
/** Describes the properties of a VkFormat, including the corresponding Metal pixel and vertex format. */
typedef struct {
VkFormat vk;
MTLPixelFormat mtl;
MTLPixelFormat mtlSubstitute;
MVKOSVersion sinceIOSVersion;
MVKOSVersion sinceMacOSVersion;
VkExtent2D blockTexelSize;
uint32_t bytesPerBlock;
VkFormat vkFormat;
MTLPixelFormat mtlPixelFormat;
MTLPixelFormat mtlPixelFormatSubstitute;
MTLVertexFormat mtlVertexFormat;
MTLVertexFormat mtlVertexFormatSubstitute;
MVKOSVersion vertexSinceIOSVersion;
MVKOSVersion vertexSinceMacOSVersion;
VkExtent2D blockTexelSize;
uint32_t bytesPerBlock;
MVKFormatType formatType;
VkFormatProperties properties;
const char* vkName;
const char* mtlName;
const char* name;
bool hasReportedSubstitution;
inline double bytesPerTexel() const { return (double)bytesPerBlock / (double)(blockTexelSize.width * blockTexelSize.height); };
inline bool isSupported() const { return (mtlPixelFormat != MTLPixelFormatInvalid); };
inline bool isSupportedOrSubstitutable() const { return isSupported() || (mtlPixelFormatSubstitute != MTLPixelFormatInvalid); };
inline bool vertexIsSupported() const { return (mtlVertexFormat != MTLVertexFormatInvalid); };
inline bool vertexIsSupportedOrSubstitutable() const { return vertexIsSupported() || (mtlVertexFormatSubstitute != MTLVertexFormatInvalid); };
} MVKVkFormatDesc;
/** Describes the properties of a MTLPixelFormat or MTLVertexFormat. */
typedef struct {
union {
MTLPixelFormat mtlPixelFormat;
MTLVertexFormat mtlVertexFormat;
};
VkFormat vkFormat;
MVKOSVersion sinceIOSVersion;
MVKOSVersion sinceMacOSVersion;
const char* name;
inline MVKOSVersion sinceOSVersion() const {
#if MVK_IOS
@ -74,20 +77,8 @@ typedef struct {
return sinceMacOSVersion;
#endif
}
inline bool isSupported() const { return (mtl != MTLPixelFormatInvalid) && (mvkOSVersion() >= sinceOSVersion()); };
inline bool isSupportedOrSubstitutable() const { return isSupported() || (mtlSubstitute != MTLPixelFormatInvalid); };
inline MVKOSVersion vertexSinceOSVersion() const {
#if MVK_IOS
return vertexSinceIOSVersion;
#endif
#if MVK_MACOS
return vertexSinceMacOSVersion;
#endif
}
inline bool vertexIsSupported() const { return (mtlVertexFormat != MTLVertexFormatInvalid) && (mvkOSVersion() >= vertexSinceOSVersion()); };
inline bool vertexIsSupportedOrSubstitutable() const { return vertexIsSupported() || (mtlVertexFormatSubstitute != MTLVertexFormatInvalid); };
} MVKFormatDesc;
inline bool isSupported() const { return (mtlPixelFormat != MTLPixelFormatInvalid) && (mvkOSVersion() >= sinceOSVersion()); };
} MVKMTLFormatDesc;
#pragma mark -
@ -247,11 +238,13 @@ public:
MVKPixelFormats() : MVKPixelFormats(nullptr, nil) {}
protected:
const MVKFormatDesc& formatDescForVkFormat(VkFormat vkFormat);
const MVKFormatDesc& formatDescForMTLPixelFormat(MTLPixelFormat mtlFormat);
const MVKFormatDesc& formatDescForMTLVertexFormat(MTLVertexFormat mtlFormat);
void initFormatCapabilities();
void buidFormatMaps();
MVKVkFormatDesc& getDescForVkFormat(VkFormat vkFormat);
MVKMTLFormatDesc& getDescForMTLPixelFormat(MTLPixelFormat mtlFormat);
MVKMTLFormatDesc& getDescForMTLVertexFormat(MTLVertexFormat mtlFormat);
void initVkFormatCapabilities();
void initMTLPixelFormatCapabilities();
void initMTLVertexFormatCapabilities();
void buildFormatMaps();
void modifyFormatCapabilitiesForMTLDevice(id<MTLDevice> mtlDevice);
void disableMTLPixelFormat(MTLPixelFormat mtlFormat);
@ -260,16 +253,16 @@ protected:
void test();
MVKVulkanAPIObject* _apiObject;
MVKFormatDesc _formatDescriptions[_vkSpecFormatCount];
uint32_t _vkFormatCount;
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 _fmtDescIndicesByVkFormatsCore[_vkFormatCoreCount];
std::unordered_map<uint32_t, uint32_t> _fmtDescIndicesByVkFormatsExt;
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 _fmtDescIndicesByMTLPixelFormats[_mtlFormatCount];
uint16_t _fmtDescIndicesByMTLVertexFormats[_mtlVertexFormatCount];
uint16_t _mtlFormatDescIndicesByMTLPixelFormats[_mtlPixelFormatCount];
uint16_t _mtlFormatDescIndicesByMTLVertexFormats[_mtlVertexFormatCount];
};

File diff suppressed because it is too large Load Diff

View File

@ -485,7 +485,7 @@ static uint16_t _fmtDescIndicesByVkFormatsCore[_vkFormatCoreCount];
static MVKFormatIndexByVkFormatMap* _pFmtDescIndicesByVkFormatsExt;
// Metal formats have small values and are mapped by simple lookup array.
static uint16_t _fmtDescIndicesByMTLPixelFormats[_mtlFormatCount];
static uint16_t _fmtDescIndicesByMTLPixelFormats[_mtlPixelFormatCount];
static uint16_t _fmtDescIndicesByMTLVertexFormats[_mtlVertexFormatCount];
/**
@ -502,7 +502,7 @@ static void MVKInitFormatMaps() {
// Set all VkFormats and MTLPixelFormats to undefined/invalid
mvkClear(_fmtDescIndicesByVkFormatsCore, _vkFormatCoreCount);
mvkClear(_fmtDescIndicesByMTLPixelFormats, _mtlFormatCount);
mvkClear(_fmtDescIndicesByMTLPixelFormats, _mtlPixelFormatCount);
mvkClear(_fmtDescIndicesByMTLVertexFormats, _mtlVertexFormatCount);
_pFmtDescIndicesByVkFormatsExt = new MVKFormatIndexByVkFormatMap();
@ -527,8 +527,12 @@ static void MVKInitFormatMaps() {
// If the Metal format is defined, create a lookup between the Metal format and an
// index to the format info. Metal formats are small, so use a simple lookup array.
if (tfm.mtl != MTLPixelFormatInvalid) { _fmtDescIndicesByMTLPixelFormats[tfm.mtl] = fmtIdx; }
if (tfm.mtlVertexFormat != MTLVertexFormatInvalid) { _fmtDescIndicesByMTLVertexFormats[tfm.mtlVertexFormat] = fmtIdx; }
if (tfm.mtl != MTLPixelFormatInvalid && !_fmtDescIndicesByMTLPixelFormats[tfm.mtl]) {
_fmtDescIndicesByMTLPixelFormats[tfm.mtl] = fmtIdx;
}
if (tfm.mtlVertexFormat != MTLVertexFormatInvalid && !_fmtDescIndicesByMTLVertexFormats[tfm.mtlVertexFormat]) {
_fmtDescIndicesByMTLVertexFormats[tfm.mtlVertexFormat] = fmtIdx;
}
}
}
@ -540,7 +544,7 @@ inline const MVKPlatformFormatDesc& formatDescForVkFormat(VkFormat vkFormat) {
// Return a reference to the format description corresponding to the MTLPixelFormat.
inline const MVKPlatformFormatDesc& formatDescForMTLPixelFormat(MTLPixelFormat mtlFormat) {
uint16_t fmtIdx = (mtlFormat < _mtlFormatCount) ? _fmtDescIndicesByMTLPixelFormats[mtlFormat] : 0;
uint16_t fmtIdx = (mtlFormat < _mtlPixelFormatCount) ? _fmtDescIndicesByMTLPixelFormats[mtlFormat] : 0;
return _formatDescriptions[fmtIdx];
}