Merge pull request #1955 from cdavis5e/4444-formats

Support the `VK_EXT_4444_formats` extension.
This commit is contained in:
Chip Davis 2023-06-23 13:07:10 -06:00 committed by GitHub
commit 591eb6bdaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 302 additions and 31 deletions

View File

@ -350,6 +350,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
- `VK_KHR_timeline_semaphore` - `VK_KHR_timeline_semaphore`
- `VK_KHR_uniform_buffer_standard_layout` - `VK_KHR_uniform_buffer_standard_layout`
- `VK_KHR_variable_pointers` - `VK_KHR_variable_pointers`
- `VK_EXT_4444_formats` *(requires 16-bit formats and either native texture swizzling or manual swizzling to be enabled)*
- `VK_EXT_buffer_device_address` *(requires GPU Tier 2 argument buffers support)* - `VK_EXT_buffer_device_address` *(requires GPU Tier 2 argument buffers support)*
- `VK_EXT_debug_marker` - `VK_EXT_debug_marker`
- `VK_EXT_debug_report` - `VK_EXT_debug_report`

View File

@ -19,6 +19,7 @@ MoltenVK 1.2.5
Released TBD Released TBD
- Add support for extensions: - Add support for extensions:
- `VK_EXT_4444_formats`
- `VK_EXT_shader_demote_to_helper_invocation` - `VK_EXT_shader_demote_to_helper_invocation`
- Ensure non-dispatch compute commands don't interfere with compute encoding state used by dispatch commands. - Ensure non-dispatch compute commands don't interfere with compute encoding state used by dispatch commands.
- Support `VK_PRESENT_MODE_IMMEDIATE_KHR` if `VkPresentTimeGOOGLE::desiredPresentTime` is zero. - Support `VK_PRESENT_MODE_IMMEDIATE_KHR` if `VkPresentTimeGOOGLE::desiredPresentTime` is zero.

View File

@ -227,6 +227,15 @@ MTLTextureSwizzle mvkMTLTextureSwizzleFromVkComponentSwizzle(VkComponentSwizzle
/** Returns all four Metal texture swizzles from the Vulkan component mapping. */ /** Returns all four Metal texture swizzles from the Vulkan component mapping. */
MTLTextureSwizzleChannels mvkMTLTextureSwizzleChannelsFromVkComponentMapping(VkComponentMapping vkMapping); MTLTextureSwizzleChannels mvkMTLTextureSwizzleChannelsFromVkComponentMapping(VkComponentMapping vkMapping);
/** Maps a clear color according to the specified VkComponentSwizzle. */
float mvkVkClearColorFloatValueFromVkComponentSwizzle(float *colors, uint32_t index, VkComponentSwizzle vkSwizzle);
/** Maps a clear color according to the specified VkComponentSwizzle. */
uint32_t mvkVkClearColorUIntValueFromVkComponentSwizzle(uint32_t *colors, uint32_t index, VkComponentSwizzle vkSwizzle);
/** Maps a clear color according to the specified VkComponentSwizzle. */
int32_t mvkVkClearColorIntValueFromVkComponentSwizzle(int32_t *colors, uint32_t index, VkComponentSwizzle vkSwizzle);
#pragma mark Mipmaps #pragma mark Mipmaps

View File

@ -374,6 +374,7 @@ bool MVKCmdBlitImage<N>::canCopyFormats(const VkImageBlit2& region) {
uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.srcSubresource.aspectMask); uint8_t srcPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.srcSubresource.aspectMask);
uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.dstSubresource.aspectMask); uint8_t dstPlaneIndex = MVKImage::getPlaneFromVkImageAspectFlags(region.dstSubresource.aspectMask);
return ((_srcImage->getMTLPixelFormat(srcPlaneIndex) == _dstImage->getMTLPixelFormat(dstPlaneIndex)) && return ((_srcImage->getMTLPixelFormat(srcPlaneIndex) == _dstImage->getMTLPixelFormat(dstPlaneIndex)) &&
!_srcImage->needsSwizzle() &&
(_dstImage->getSampleCount() == _srcImage->getSampleCount())); (_dstImage->getSampleCount() == _srcImage->getSampleCount()));
} }
@ -456,7 +457,7 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
uint32_t copyCnt = 0; uint32_t copyCnt = 0;
uint32_t blitCnt = 0; uint32_t blitCnt = 0;
// Separate BLITs into those that are really just simple texure region copies, // Separate BLITs into those that are really just simple texture region copies,
// and those that require rendering // and those that require rendering
for (auto& vkIB : _vkImageBlits) { for (auto& vkIB : _vkImageBlits) {
if (canCopyFormats(vkIB) && canCopy(vkIB)) { if (canCopyFormats(vkIB) && canCopy(vkIB)) {
@ -500,6 +501,15 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
id<MTLTexture> srcMTLTex = _srcImage->getMTLTexture(srcPlaneIndex); id<MTLTexture> srcMTLTex = _srcImage->getMTLTexture(srcPlaneIndex);
id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture(dstPlaneIndex); id<MTLTexture> dstMTLTex = _dstImage->getMTLTexture(dstPlaneIndex);
if (blitCnt && srcMTLTex && dstMTLTex) { if (blitCnt && srcMTLTex && dstMTLTex) {
if (cmdEncoder->getDevice()->_pMetalFeatures->nativeTextureSwizzle &&
_srcImage->needsSwizzle()) {
// Use a view that has a swizzle on it.
srcMTLTex = [[srcMTLTex newTextureViewWithPixelFormat:srcMTLTex.pixelFormat
textureType:srcMTLTex.textureType
levels:NSMakeRange(0, srcMTLTex.mipmapLevelCount)
slices:NSMakeRange(0, srcMTLTex.arrayLength)
swizzle:_srcImage->getPixelFormats()->getMTLTextureSwizzleChannels(_srcImage->getVkFormat())] autorelease];
}
cmdEncoder->endCurrentMetalEncoding(); cmdEncoder->endCurrentMetalEncoding();
MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor]; MTLRenderPassDescriptor* mtlRPD = [MTLRenderPassDescriptor renderPassDescriptor];
@ -549,6 +559,14 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
blitKey.srcFilter = mvkMTLSamplerMinMagFilterFromVkFilter(_filter); blitKey.srcFilter = mvkMTLSamplerMinMagFilterFromVkFilter(_filter);
blitKey.srcAspect = mvkIBR.region.srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); blitKey.srcAspect = mvkIBR.region.srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
blitKey.dstSampleCount = mvkSampleCountFromVkSampleCountFlagBits(_dstImage->getSampleCount()); blitKey.dstSampleCount = mvkSampleCountFromVkSampleCountFlagBits(_dstImage->getSampleCount());
if (!cmdEncoder->getDevice()->_pMetalFeatures->nativeTextureSwizzle &&
_srcImage->needsSwizzle()) {
VkComponentMapping vkMapping = _srcImage->getPixelFormats()->getVkComponentMapping(_srcImage->getVkFormat());
blitKey.srcSwizzleR = vkMapping.r;
blitKey.srcSwizzleG = vkMapping.g;
blitKey.srcSwizzleB = vkMapping.b;
blitKey.srcSwizzleA = vkMapping.a;
}
id<MTLRenderPipelineState> mtlRPS = cmdEncoder->getCommandEncodingPool()->getCmdBlitImageMTLRenderPipelineState(blitKey); id<MTLRenderPipelineState> mtlRPS = cmdEncoder->getCommandEncodingPool()->getCmdBlitImageMTLRenderPipelineState(blitKey);
bool isBlittingDepth = mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT)); bool isBlittingDepth = mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT));
bool isBlittingStencil = mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_STENCIL_BIT)); bool isBlittingStencil = mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_STENCIL_BIT));

View File

@ -37,20 +37,31 @@ class MVKQueryPool;
* This structure can be used as a key in a std::map and std::unordered_map. * This structure can be used as a key in a std::map and std::unordered_map.
*/ */
typedef struct MVKRPSKeyBlitImg { typedef struct MVKRPSKeyBlitImg {
uint16_t srcMTLPixelFormat = 0; /**< as MTLPixelFormat */ uint16_t srcMTLPixelFormat : 12; /**< as MTLPixelFormat */
uint16_t dstMTLPixelFormat = 0; /**< as MTLPixelFormat */ uint16_t dstMTLPixelFormat : 12; /**< as MTLPixelFormat */
uint8_t srcMTLTextureType = 0; /**< as MTLTextureType */ uint8_t srcMTLTextureType : 4; /**< as MTLTextureType */
uint8_t srcFilter : 4; /**< as MTLSamplerMinMagFilter */
uint8_t srcAspect = 0; /**< as VkImageAspectFlags */ uint8_t srcAspect = 0; /**< as VkImageAspectFlags */
uint8_t srcFilter = 0; /**< as MTLSamplerMinMagFilter */
uint8_t dstSampleCount = 0; uint8_t dstSampleCount = 0;
uint8_t srcSwizzleR : 4; /**< as VkComponentSwizzle */
uint8_t srcSwizzleG : 4; /**< as VkComponentSwizzle */
uint8_t srcSwizzleB : 4; /**< as VkComponentSwizzle */
uint8_t srcSwizzleA : 4; /**< as VkComponentSwizzle */
MVKRPSKeyBlitImg() : srcMTLPixelFormat(0), dstMTLPixelFormat(0), srcMTLTextureType(0), srcFilter(0),
srcSwizzleR(0), srcSwizzleG(0), srcSwizzleB(0), srcSwizzleA(0) {}
bool operator==(const MVKRPSKeyBlitImg& rhs) const { bool operator==(const MVKRPSKeyBlitImg& rhs) const {
if (srcMTLPixelFormat != rhs.srcMTLPixelFormat) { return false; } if (srcMTLPixelFormat != rhs.srcMTLPixelFormat) { return false; }
if (dstMTLPixelFormat != rhs.dstMTLPixelFormat) { return false; } if (dstMTLPixelFormat != rhs.dstMTLPixelFormat) { return false; }
if (srcMTLTextureType != rhs.srcMTLTextureType) { return false; } if (srcMTLTextureType != rhs.srcMTLTextureType) { return false; }
if (srcAspect != rhs.srcAspect) { return false; }
if (srcFilter != rhs.srcFilter) { return false; } if (srcFilter != rhs.srcFilter) { return false; }
if (srcAspect != rhs.srcAspect) { return false; }
if (dstSampleCount != rhs.dstSampleCount) { return false; } if (dstSampleCount != rhs.dstSampleCount) { return false; }
if (srcSwizzleR != rhs.srcSwizzleR) { return false; }
if (srcSwizzleG != rhs.srcSwizzleG) { return false; }
if (srcSwizzleB != rhs.srcSwizzleB) { return false; }
if (srcSwizzleA != rhs.srcSwizzleA) { return false; }
return true; return true;
} }
@ -70,23 +81,40 @@ typedef struct MVKRPSKeyBlitImg {
srcMTLTextureType == MTLTextureType1DArray); srcMTLTextureType == MTLTextureType1DArray);
} }
VkComponentMapping getSrcSwizzle() {
return { (VkComponentSwizzle)srcSwizzleR, (VkComponentSwizzle)srcSwizzleG,
(VkComponentSwizzle)srcSwizzleB, (VkComponentSwizzle)srcSwizzleA };
}
std::size_t hash() const { std::size_t hash() const {
std::size_t hash = srcMTLPixelFormat; std::size_t hash = srcMTLPixelFormat;
hash <<= 16; hash <<= 12;
hash |= dstMTLPixelFormat; hash |= dstMTLPixelFormat;
hash <<= 8; hash <<= 4;
hash |= srcMTLTextureType; hash |= srcMTLTextureType;
hash <<= 4;
hash |= srcFilter;
hash <<= 8; hash <<= 8;
hash |= srcAspect; hash |= srcAspect;
hash <<= 8;
hash |= srcFilter;
hash <<= 8; hash <<= 8;
hash |= dstSampleCount; hash |= dstSampleCount;
hash <<= 4;
hash |= srcSwizzleR;
hash <<= 4;
hash |= srcSwizzleG;
hash <<= 4;
hash |= srcSwizzleB;
hash <<= 4;
hash |= srcSwizzleA;
return hash; return hash;
} }

View File

@ -167,6 +167,25 @@ id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipeli
return rps; return rps;
} }
static char getSwizzleChar(char defaultChar, VkComponentSwizzle vkSwizzle) {
switch (vkSwizzle) {
case VK_COMPONENT_SWIZZLE_IDENTITY: return defaultChar;
// FIXME: 0 and 1 (currently not used in any default swizzles)
case VK_COMPONENT_SWIZZLE_R: return 'x';
case VK_COMPONENT_SWIZZLE_G: return 'y';
case VK_COMPONENT_SWIZZLE_B: return 'z';
case VK_COMPONENT_SWIZZLE_A: return 'w';
default: return defaultChar;
}
}
static void getSwizzleString(char swizzleStr[4], VkComponentMapping vkMapping) {
swizzleStr[0] = getSwizzleChar('x', vkMapping.r);
swizzleStr[1] = getSwizzleChar('y', vkMapping.g);
swizzleStr[2] = getSwizzleChar('z', vkMapping.b);
swizzleStr[3] = getSwizzleChar('w', vkMapping.a);
}
id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg& blitKey) { id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg& blitKey) {
@autoreleasepool { @autoreleasepool {
bool isLayeredBlit = blitKey.dstSampleCount > 1 ? _device->_pMetalFeatures->multisampleLayeredRendering : _device->_pMetalFeatures->layeredRendering; bool isLayeredBlit = blitKey.dstSampleCount > 1 ? _device->_pMetalFeatures->multisampleLayeredRendering : _device->_pMetalFeatures->layeredRendering;
@ -177,6 +196,7 @@ id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg&
NSString* typePrefix = @"texture"; NSString* typePrefix = @"texture";
NSString* typeSuffix; NSString* typeSuffix;
NSString* coordArg; NSString* coordArg;
char swizzleArg[4] = { 'x', 'y', 'z', 'w' };
if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT))) { if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT))) {
typePrefix = @"depth"; typePrefix = @"depth";
} }
@ -208,6 +228,9 @@ id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg&
} }
NSString* sliceArg = isArrayType ? (isLayeredBlit ? @", subRez.slice + varyings.v_layer" : @", subRez.slice") : @""; NSString* sliceArg = isArrayType ? (isLayeredBlit ? @", subRez.slice + varyings.v_layer" : @", subRez.slice") : @"";
NSString* srcFilter = isLinearFilter ? @"linear" : @"nearest"; NSString* srcFilter = isLinearFilter ? @"linear" : @"nearest";
if (!getDevice()->_pMetalFeatures->nativeTextureSwizzle) {
getSwizzleString(swizzleArg, blitKey.getSrcSwizzle());
}
NSMutableString* msl = [NSMutableString stringWithCapacity: (2 * KIBI) ]; NSMutableString* msl = [NSMutableString stringWithCapacity: (2 * KIBI) ];
[msl appendLineMVK: @"#include <metal_stdlib>"]; [msl appendLineMVK: @"#include <metal_stdlib>"];
@ -263,15 +286,15 @@ id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg&
[msl appendLineMVK: @" constant TexSubrez& subRez [[buffer(0)]]) {"]; [msl appendLineMVK: @" constant TexSubrez& subRez [[buffer(0)]]) {"];
[msl appendLineMVK: @" FragmentOutputs out;"]; [msl appendLineMVK: @" FragmentOutputs out;"];
if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT))) { if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT))) {
[msl appendFormat: @" out.depth = tex.sample(ce_sampler, varyings.v_texCoord%@%@, level(subRez.lod));", coordArg, sliceArg]; [msl appendFormat: @" out.depth = tex.sample(ce_sampler, varyings.v_texCoord%@%@, level(subRez.lod)).%c;", coordArg, sliceArg, swizzleArg[0]];
[msl appendLineMVK]; [msl appendLineMVK];
} }
if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_STENCIL_BIT))) { if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_STENCIL_BIT))) {
[msl appendFormat: @" out.stencil = stencilTex.sample(ce_stencil_sampler, varyings.v_texCoord%@%@, level(subRez.lod)).x;", coordArg, sliceArg]; [msl appendFormat: @" out.stencil = stencilTex.sample(ce_stencil_sampler, varyings.v_texCoord%@%@, level(subRez.lod)).%c;", coordArg, sliceArg, swizzleArg[0]];
[msl appendLineMVK]; [msl appendLineMVK];
} }
if (!mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) { if (!mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
[msl appendFormat: @" out.color = tex.sample(ce_sampler, varyings.v_texCoord%@%@, level(subRez.lod));", coordArg, sliceArg]; [msl appendFormat: @" out.color = tex.sample(ce_sampler, varyings.v_texCoord%@%@, level(subRez.lod)).%.4s;", coordArg, sliceArg, swizzleArg];
[msl appendLineMVK]; [msl appendLineMVK];
} }
[msl appendLineMVK: @" return out;"]; [msl appendLineMVK: @" return out;"];

View File

@ -371,6 +371,15 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
portabilityFeatures->vertexAttributeAccessBeyondStride = true; // Costs additional buffers. Should make configuration switch. portabilityFeatures->vertexAttributeAccessBeyondStride = true; // Costs additional buffers. Should make configuration switch.
break; break;
} }
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
auto* formatFeatures = (VkPhysicalDevice4444FormatsFeaturesEXT*)next;
bool canSupport4444 = _metalFeatures.tileBasedDeferredRendering &&
(_metalFeatures.nativeTextureSwizzle ||
mvkConfig().fullImageViewSwizzle);
formatFeatures->formatA4R4G4B4 = canSupport4444;
formatFeatures->formatA4B4G4R4 = canSupport4444;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: {
auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next; auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next;
interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups; interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups;

View File

@ -62,6 +62,7 @@ MVK_DEVICE_FEATURE(VariablePointer, VARIABLE_POINTER,
MVK_DEVICE_FEATURE(VulkanMemoryModel, VULKAN_MEMORY_MODEL, 3) MVK_DEVICE_FEATURE(VulkanMemoryModel, VULKAN_MEMORY_MODEL, 3)
MVK_DEVICE_FEATURE_EXTN(FragmentShaderBarycentric, FRAGMENT_SHADER_BARYCENTRIC, KHR, 1) MVK_DEVICE_FEATURE_EXTN(FragmentShaderBarycentric, FRAGMENT_SHADER_BARYCENTRIC, KHR, 1)
MVK_DEVICE_FEATURE_EXTN(PortabilitySubset, PORTABILITY_SUBSET, KHR, 15) MVK_DEVICE_FEATURE_EXTN(PortabilitySubset, PORTABILITY_SUBSET, KHR, 15)
MVK_DEVICE_FEATURE_EXTN(4444Formats, 4444_FORMATS, EXT, 2)
MVK_DEVICE_FEATURE_EXTN(FragmentShaderInterlock, FRAGMENT_SHADER_INTERLOCK, EXT, 3) MVK_DEVICE_FEATURE_EXTN(FragmentShaderInterlock, FRAGMENT_SHADER_INTERLOCK, EXT, 3)
MVK_DEVICE_FEATURE_EXTN(PipelineCreationCacheControl, PIPELINE_CREATION_CACHE_CONTROL, EXT, 1) MVK_DEVICE_FEATURE_EXTN(PipelineCreationCacheControl, PIPELINE_CREATION_CACHE_CONTROL, EXT, 1)
MVK_DEVICE_FEATURE_EXTN(Robustness2, ROBUSTNESS_2, EXT, 3) MVK_DEVICE_FEATURE_EXTN(Robustness2, ROBUSTNESS_2, EXT, 3)

View File

@ -224,6 +224,9 @@ public:
/** Returns the number of planes of this image view. */ /** Returns the number of planes of this image view. */
uint8_t getPlaneCount() { return _planes.size(); } uint8_t getPlaneCount() { return _planes.size(); }
/** Returns whether or not the image format requires swizzling. */
bool needsSwizzle() { return getPixelFormats()->needsSwizzle(_vkFormat); }
/** Populates the specified layout for the specified sub-resource. */ /** Populates the specified layout for the specified sub-resource. */
VkResult getSubresourceLayout(const VkImageSubresource* pSubresource, VkResult getSubresourceLayout(const VkImageSubresource* pSubresource,
VkSubresourceLayout* pLayout); VkSubresourceLayout* pLayout);

View File

@ -1575,6 +1575,26 @@ VkResult MVKImageViewPlane::initSwizzledMTLPixelFormat(const VkImageViewCreateIn
VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask; VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask;
#define adjustComponentSwizzleValue(comp, currVal, newVal) if (_componentSwizzle.comp == VK_COMPONENT_SWIZZLE_ ##currVal) { _componentSwizzle.comp = VK_COMPONENT_SWIZZLE_ ##newVal; } #define adjustComponentSwizzleValue(comp, currVal, newVal) if (_componentSwizzle.comp == VK_COMPONENT_SWIZZLE_ ##currVal) { _componentSwizzle.comp = VK_COMPONENT_SWIZZLE_ ##newVal; }
#define adjustAnyComponentSwizzleValue(comp, I, R, G, B, A) \
switch (_componentSwizzle.comp) { \
case VK_COMPONENT_SWIZZLE_IDENTITY: \
_componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##I; \
break; \
case VK_COMPONENT_SWIZZLE_R: \
_componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##R; \
break; \
case VK_COMPONENT_SWIZZLE_G: \
_componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##G; \
break; \
case VK_COMPONENT_SWIZZLE_B: \
_componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##B; \
break; \
case VK_COMPONENT_SWIZZLE_A: \
_componentSwizzle.comp = VK_COMPONENT_SWIZZLE_##A; \
break; \
default: \
break; \
}
// Use swizzle adjustment to bridge some differences between Vulkan and Metal pixel formats. // Use swizzle adjustment to bridge some differences between Vulkan and Metal pixel formats.
// Do this ahead of other tests and adjustments so that swizzling will be enabled by tests below. // Do this ahead of other tests and adjustments so that swizzling will be enabled by tests below.
@ -1589,6 +1609,24 @@ VkResult MVKImageViewPlane::initSwizzledMTLPixelFormat(const VkImageViewCreateIn
adjustComponentSwizzleValue(a, IDENTITY, ONE); adjustComponentSwizzleValue(a, IDENTITY, ONE);
break; break;
case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
// Metal doesn't (publicly) support this directly, so use a swizzle to get the ordering right.
// n.b. **Do NOT use adjustComponentSwizzleValue if multiple values need substitution,
// and some of the substitutes are keys for other substitutions!**
adjustAnyComponentSwizzleValue(r, G, G, B, A, R);
adjustAnyComponentSwizzleValue(g, B, G, B, A, R);
adjustAnyComponentSwizzleValue(b, A, G, B, A, R);
adjustAnyComponentSwizzleValue(a, R, G, B, A, R);
break;
case VK_FORMAT_A4B4G4R4_UNORM_PACK16:
// Metal doesn't support this directly, so use a swizzle to get the ordering right.
adjustAnyComponentSwizzleValue(r, A, A, B, G, R);
adjustAnyComponentSwizzleValue(g, B, A, B, G, R);
adjustAnyComponentSwizzleValue(b, G, A, B, G, R);
adjustAnyComponentSwizzleValue(a, R, A, B, G, R);
break;
default: default:
break; break;
} }

View File

@ -148,6 +148,7 @@ typedef struct MVKVkFormatDesc {
uint32_t bytesPerBlock; uint32_t bytesPerBlock;
MVKFormatType formatType; MVKFormatType formatType;
VkFormatProperties properties; VkFormatProperties properties;
VkComponentMapping componentMapping;
const char* name; const char* name;
bool hasReportedSubstitution; bool hasReportedSubstitution;
@ -158,6 +159,13 @@ typedef struct MVKVkFormatDesc {
inline bool vertexIsSupported() const { return (mtlVertexFormat != MTLVertexFormatInvalid); }; inline bool vertexIsSupported() const { return (mtlVertexFormat != MTLVertexFormatInvalid); };
inline bool vertexIsSupportedOrSubstitutable() const { return vertexIsSupported() || (mtlVertexFormatSubstitute != MTLVertexFormatInvalid); }; inline bool vertexIsSupportedOrSubstitutable() const { return vertexIsSupported() || (mtlVertexFormatSubstitute != MTLVertexFormatInvalid); };
bool needsSwizzle() const {
return componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY ||
componentMapping.g != VK_COMPONENT_SWIZZLE_IDENTITY ||
componentMapping.b != VK_COMPONENT_SWIZZLE_IDENTITY ||
componentMapping.a != VK_COMPONENT_SWIZZLE_IDENTITY;
}
} MVKVkFormatDesc; } MVKVkFormatDesc;
/** Describes the properties of a MTLPixelFormat or MTLVertexFormat. */ /** Describes the properties of a MTLPixelFormat or MTLVertexFormat. */
@ -320,6 +328,21 @@ public:
*/ */
size_t getBytesPerLayer(MTLPixelFormat mtlFormat, size_t bytesPerRow, uint32_t texelRowsPerLayer); size_t getBytesPerLayer(MTLPixelFormat mtlFormat, size_t bytesPerRow, uint32_t texelRowsPerLayer);
/** Returns whether or not the specified Vulkan format requires swizzling to use with Metal. */
bool needsSwizzle(VkFormat vkFormat);
/** Returns any VkComponentMapping needed to use the specified Vulkan format. */
VkComponentMapping getVkComponentMapping(VkFormat vkFormat);
/**
* Returns the inverse of the VkComponentMapping needed to use the specified Vulkan format.
* If the original mapping is not a one-to-one function, the behaviour is undefined.
*/
VkComponentMapping getInverseComponentMapping(VkFormat vkFormat);
/** Returns any MTLTextureSwizzleChannels needed to use the specified Vulkan format. */
MTLTextureSwizzleChannels getMTLTextureSwizzleChannels(VkFormat vkFormat);
/** Returns the default properties for the specified Vulkan format. */ /** Returns the default properties for the specified Vulkan format. */
VkFormatProperties& getVkFormatProperties(VkFormat vkFormat); VkFormatProperties& getVkFormatProperties(VkFormat vkFormat);

View File

@ -377,6 +377,44 @@ size_t MVKPixelFormats::getBytesPerLayer(MTLPixelFormat mtlFormat, size_t bytesP
return mvkCeilingDivide(texelRowsPerLayer, getVkFormatDesc(mtlFormat).blockTexelSize.height) * bytesPerRow; return mvkCeilingDivide(texelRowsPerLayer, getVkFormatDesc(mtlFormat).blockTexelSize.height) * bytesPerRow;
} }
bool MVKPixelFormats::needsSwizzle(VkFormat vkFormat) {
return getVkFormatDesc(vkFormat).needsSwizzle();
}
VkComponentMapping MVKPixelFormats::getVkComponentMapping(VkFormat vkFormat) {
return getVkFormatDesc(vkFormat).componentMapping;
}
VkComponentMapping MVKPixelFormats::getInverseComponentMapping(VkFormat vkFormat) {
#define INVERT_SWIZZLE(x, X, Y) \
case VK_COMPONENT_SWIZZLE_##X: \
inverse.x = VK_COMPONENT_SWIZZLE_##Y; \
break
#define INVERT_MAPPING(y, Y) \
switch (mapping.y) { \
case VK_COMPONENT_SWIZZLE_IDENTITY: \
inverse.y = VK_COMPONENT_SWIZZLE_IDENTITY; \
break; \
INVERT_SWIZZLE(r, R, Y); \
INVERT_SWIZZLE(g, G, Y); \
INVERT_SWIZZLE(b, B, Y); \
INVERT_SWIZZLE(a, A, Y); \
default: break; \
}
VkComponentMapping mapping = getVkComponentMapping(vkFormat), inverse;
INVERT_MAPPING(r, R)
INVERT_MAPPING(g, G)
INVERT_MAPPING(b, B)
INVERT_MAPPING(a, A)
return inverse;
#undef INVERT_MAPPING
#undef INVERT_SWIZZLE
}
MTLTextureSwizzleChannels MVKPixelFormats::getMTLTextureSwizzleChannels(VkFormat vkFormat) {
return mvkMTLTextureSwizzleChannelsFromVkComponentMapping(getVkComponentMapping(vkFormat));
}
VkFormatProperties& MVKPixelFormats::getVkFormatProperties(VkFormat vkFormat) { VkFormatProperties& MVKPixelFormats::getVkFormatProperties(VkFormat vkFormat) {
return getVkFormatDesc(vkFormat).properties; return getVkFormatDesc(vkFormat).properties;
} }
@ -464,13 +502,18 @@ MTLVertexFormat MVKPixelFormats::getMTLVertexFormat(VkFormat vkFormat) {
MTLClearColor MVKPixelFormats::getMTLClearColor(VkClearValue vkClearValue, VkFormat vkFormat) { MTLClearColor MVKPixelFormats::getMTLClearColor(VkClearValue vkClearValue, VkFormat vkFormat) {
MTLClearColor mtlClr; MTLClearColor mtlClr;
// The VkComponentMapping (and its MTLTextureSwizzleChannels equivalent) define the *sources*
// for the texture color components for reading. Since we're *writing* to the texture,
// we need to *invert* the mapping.
// n.b. Bad things might happen if the original swizzle isn't one-to-one!
VkComponentMapping inverseMap = getInverseComponentMapping(vkFormat);
switch (getFormatType(vkFormat)) { switch (getFormatType(vkFormat)) {
case kMVKFormatColorHalf: case kMVKFormatColorHalf:
case kMVKFormatColorFloat: case kMVKFormatColorFloat: {
mtlClr.red = vkClearValue.color.float32[0]; mtlClr.red = mvkVkClearColorFloatValueFromVkComponentSwizzle(vkClearValue.color.float32, 0, inverseMap.r);
mtlClr.green = vkClearValue.color.float32[1]; mtlClr.green = mvkVkClearColorFloatValueFromVkComponentSwizzle(vkClearValue.color.float32, 1, inverseMap.g);
mtlClr.blue = vkClearValue.color.float32[2]; mtlClr.blue = mvkVkClearColorFloatValueFromVkComponentSwizzle(vkClearValue.color.float32, 2, inverseMap.b);
mtlClr.alpha = vkClearValue.color.float32[3]; mtlClr.alpha = mvkVkClearColorFloatValueFromVkComponentSwizzle(vkClearValue.color.float32, 3, inverseMap.a);
if (_physicalDevice && _physicalDevice->getMetalFeatures()->clearColorFloatRounding == MVK_FLOAT_ROUNDING_DOWN) { if (_physicalDevice && _physicalDevice->getMetalFeatures()->clearColorFloatRounding == MVK_FLOAT_ROUNDING_DOWN) {
// For normalized formats, increment the clear value by half the ULP // For normalized formats, increment the clear value by half the ULP
@ -486,6 +529,8 @@ MTLClearColor MVKPixelFormats::getMTLClearColor(VkClearValue vkClearValue, VkFor
#define OFFSET_SNORM(COLOR, BIT_WIDTH) OFFSET_NORM(-1.0, COLOR, BIT_WIDTH - 1) #define OFFSET_SNORM(COLOR, BIT_WIDTH) OFFSET_NORM(-1.0, COLOR, BIT_WIDTH - 1)
switch (vkFormat) { switch (vkFormat) {
case VK_FORMAT_R4G4B4A4_UNORM_PACK16: case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
case VK_FORMAT_A4B4G4R4_UNORM_PACK16:
OFFSET_UNORM(red, 4) OFFSET_UNORM(red, 4)
OFFSET_UNORM(green, 4) OFFSET_UNORM(green, 4)
OFFSET_UNORM(blue, 4) OFFSET_UNORM(blue, 4)
@ -571,21 +616,22 @@ MTLClearColor MVKPixelFormats::getMTLClearColor(VkClearValue vkClearValue, VkFor
#undef OFFSET_NORM #undef OFFSET_NORM
} }
break; break;
}
case kMVKFormatColorUInt8: case kMVKFormatColorUInt8:
case kMVKFormatColorUInt16: case kMVKFormatColorUInt16:
case kMVKFormatColorUInt32: case kMVKFormatColorUInt32:
mtlClr.red = vkClearValue.color.uint32[0]; mtlClr.red = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 0, inverseMap.r);
mtlClr.green = vkClearValue.color.uint32[1]; mtlClr.green = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 1, inverseMap.g);
mtlClr.blue = vkClearValue.color.uint32[2]; mtlClr.blue = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 2, inverseMap.b);
mtlClr.alpha = vkClearValue.color.uint32[3]; mtlClr.alpha = mvkVkClearColorUIntValueFromVkComponentSwizzle(vkClearValue.color.uint32, 3, inverseMap.a);
break; break;
case kMVKFormatColorInt8: case kMVKFormatColorInt8:
case kMVKFormatColorInt16: case kMVKFormatColorInt16:
case kMVKFormatColorInt32: case kMVKFormatColorInt32:
mtlClr.red = vkClearValue.color.int32[0]; mtlClr.red = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 0, inverseMap.r);
mtlClr.green = vkClearValue.color.int32[1]; mtlClr.green = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 1, inverseMap.g);
mtlClr.blue = vkClearValue.color.int32[2]; mtlClr.blue = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 2, inverseMap.b);
mtlClr.alpha = vkClearValue.color.int32[3]; mtlClr.alpha = mvkVkClearColorIntValueFromVkComponentSwizzle(vkClearValue.color.int32, 3, inverseMap.a);
break; break;
default: default:
mtlClr.red = 0.0; mtlClr.red = 0.0;
@ -756,16 +802,21 @@ MVKPixelFormats::MVKPixelFormats(MVKPhysicalDevice* physicalDevice) : _physicalD
buildVkFormatMaps(); buildVkFormatMaps();
} }
#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) \ #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); \ 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, \ _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_FORMAT_" #VK_FMT, false } 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) \ #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) 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)
#define addVkFormatDescSwizzled(VK_FMT, MTL_FMT, MTL_FMT_ALT, MTL_VTX_FMT, MTL_VTX_FMT_ALT, BLK_W, BLK_H, BLK_BYTE_CNT, MVK_FMT_TYPE, SWIZ_R, SWIZ_G, SWIZ_B, SWIZ_A) \
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, SWIZ_R, SWIZ_G, SWIZ_B, SWIZ_A)
#define addVkFormatDescChromaSubsampling(VK_FMT, MTL_FMT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT) \ #define addVkFormatDescChromaSubsampling(VK_FMT, MTL_FMT, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT) \
addVkFormatDescFull(VK_FMT, MTL_FMT, Invalid, Invalid, Invalid, CSPC, CSCB, BLK_W, BLK_H, BLK_BYTE_CNT, ColorFloat) 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() { void MVKPixelFormats::initVkFormatCapabilities() {
@ -781,6 +832,8 @@ void MVKPixelFormats::initVkFormatCapabilities() {
addVkFormatDesc( R4G4_UNORM_PACK8, Invalid, Invalid, Invalid, Invalid, 1, 1, 1, ColorFloat ); addVkFormatDesc( R4G4_UNORM_PACK8, Invalid, Invalid, Invalid, Invalid, 1, 1, 1, ColorFloat );
addVkFormatDesc( R4G4B4A4_UNORM_PACK16, ABGR4Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat ); addVkFormatDesc( R4G4B4A4_UNORM_PACK16, ABGR4Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat );
addVkFormatDesc( B4G4R4A4_UNORM_PACK16, Invalid, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat ); addVkFormatDesc( B4G4R4A4_UNORM_PACK16, Invalid, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat );
addVkFormatDescSwizzled( A4R4G4B4_UNORM_PACK16, ABGR4Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat, G, B, A, R );
addVkFormatDescSwizzled( A4B4G4R4_UNORM_PACK16, ABGR4Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat, A, B, G, R );
addVkFormatDesc( R5G6B5_UNORM_PACK16, B5G6R5Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat ); addVkFormatDesc( R5G6B5_UNORM_PACK16, B5G6R5Unorm, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat );
addVkFormatDesc( B5G6R5_UNORM_PACK16, Invalid, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat ); addVkFormatDesc( B5G6R5_UNORM_PACK16, Invalid, Invalid, Invalid, Invalid, 1, 1, 2, ColorFloat );
@ -1962,6 +2015,23 @@ void MVKPixelFormats::buildVkFormatMaps() {
_vkFormatDescIndicesByVkFormatsExt[vkFmt] = fmtIdx; _vkFormatDescIndicesByVkFormatsExt[vkFmt] = fmtIdx;
} }
if (vkDesc.needsSwizzle()) {
if (_physicalDevice) {
id<MTLDevice> mtlDev = _physicalDevice->getMTLDevice();
#if MVK_MACCAT
bool supportsNativeTextureSwizzle = [mtlDev supportsFamily: MTLGPUFamilyMacCatalyst2];
#elif MVK_MACOS
bool supportsNativeTextureSwizzle = mvkOSVersionIsAtLeast(10.15) && [mtlDev supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily2_v1];
#endif
#if MVK_IOS || MVK_TVOS
bool supportsNativeTextureSwizzle = mtlDev && mvkOSVersionIsAtLeast(13.0);
#endif
if (!supportsNativeTextureSwizzle && !mvkConfig().fullImageViewSwizzle) {
vkDesc.mtlPixelFormat = vkDesc.mtlPixelFormatSubstitute = MTLPixelFormatInvalid;
}
}
}
// Populate the back reference from the Metal formats to the Vulkan format. // Populate the back reference from the Metal formats to the Vulkan format.
// Validate the corresponding Metal formats for the platform, and clear them // Validate the corresponding Metal formats for the platform, and clear them
// in the Vulkan format if not supported. // in the Vulkan format if not supported.
@ -2078,6 +2148,13 @@ void MVKPixelFormats::setFormatProperties(MVKVkFormatDesc& vkDesc) {
mvkDisableFlags(vkProps.optimalTilingFeatures, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT)); mvkDisableFlags(vkProps.optimalTilingFeatures, (VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT));
} }
// These formats require swizzling. In order to support rendering, we'll have to swizzle
// in the fragment shader, but that hasn't been implemented yet.
if (vkDesc.needsSwizzle()) {
mvkDisableFlags(vkProps.optimalTilingFeatures, (kMVKVkFormatFeatureFlagsTexColorAtt |
kMVKVkFormatFeatureFlagsTexBlend));
}
// Linear tiling is not available to depth/stencil or compressed formats. // Linear tiling is not available to depth/stencil or compressed formats.
// GBGR and BGRG formats also do not support linear tiling in Metal. // GBGR and BGRG formats also do not support linear tiling in Metal.
if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed || if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed ||

View File

@ -93,6 +93,7 @@ MVK_EXTENSION(KHR_timeline_semaphore, KHR_TIMELINE_SEMAPHORE,
MVK_EXTENSION(KHR_uniform_buffer_standard_layout, KHR_UNIFORM_BUFFER_STANDARD_LAYOUT, DEVICE, 10.11, 8.0) MVK_EXTENSION(KHR_uniform_buffer_standard_layout, KHR_UNIFORM_BUFFER_STANDARD_LAYOUT, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, DEVICE, 10.11, 8.0) MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, DEVICE, 10.11, 8.0)
MVK_EXTENSION(KHR_vulkan_memory_model, KHR_VULKAN_MEMORY_MODEL, DEVICE, MVK_NA, MVK_NA) MVK_EXTENSION(KHR_vulkan_memory_model, KHR_VULKAN_MEMORY_MODEL, DEVICE, MVK_NA, MVK_NA)
MVK_EXTENSION(EXT_4444_formats, EXT_4444_FORMATS, DEVICE, 11.0, 13.0)
MVK_EXTENSION(EXT_buffer_device_address, EXT_BUFFER_DEVICE_ADDRESS, DEVICE, 13.0, 16.0) MVK_EXTENSION(EXT_buffer_device_address, EXT_BUFFER_DEVICE_ADDRESS, DEVICE, 13.0, 16.0)
MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, DEVICE, 10.11, 8.0) MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, DEVICE, 10.11, 8.0)
MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, INSTANCE, 10.11, 8.0) MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, INSTANCE, 10.11, 8.0)

View File

@ -228,6 +228,45 @@ MVK_PUBLIC_SYMBOL MTLTextureSwizzleChannels mvkMTLTextureSwizzleChannelsFromVkCo
#undef convert #undef convert
} }
MVK_PUBLIC_SYMBOL float mvkVkClearColorFloatValueFromVkComponentSwizzle(float *colors, uint32_t index, VkComponentSwizzle vkSwizzle) {
switch (vkSwizzle) {
case VK_COMPONENT_SWIZZLE_IDENTITY: return colors[index];
case VK_COMPONENT_SWIZZLE_ZERO: return 0.f;
case VK_COMPONENT_SWIZZLE_ONE: return 1.f;
case VK_COMPONENT_SWIZZLE_R: return colors[0];
case VK_COMPONENT_SWIZZLE_G: return colors[1];
case VK_COMPONENT_SWIZZLE_B: return colors[2];
case VK_COMPONENT_SWIZZLE_A: return colors[3];
default: return colors[index];
}
}
MVK_PUBLIC_SYMBOL uint32_t mvkVkClearColorUIntValueFromVkComponentSwizzle(uint32_t *colors, uint32_t index, VkComponentSwizzle vkSwizzle) {
switch (vkSwizzle) {
case VK_COMPONENT_SWIZZLE_IDENTITY: return colors[index];
case VK_COMPONENT_SWIZZLE_ZERO: return 0U;
case VK_COMPONENT_SWIZZLE_ONE: return 1U;
case VK_COMPONENT_SWIZZLE_R: return colors[0];
case VK_COMPONENT_SWIZZLE_G: return colors[1];
case VK_COMPONENT_SWIZZLE_B: return colors[2];
case VK_COMPONENT_SWIZZLE_A: return colors[3];
default: return colors[index];
}
}
MVK_PUBLIC_SYMBOL int32_t mvkVkClearColorIntValueFromVkComponentSwizzle(int32_t *colors, uint32_t index, VkComponentSwizzle vkSwizzle) {
switch (vkSwizzle) {
case VK_COMPONENT_SWIZZLE_IDENTITY: return colors[index];
case VK_COMPONENT_SWIZZLE_ZERO: return 0;
case VK_COMPONENT_SWIZZLE_ONE: return 1;
case VK_COMPONENT_SWIZZLE_R: return colors[0];
case VK_COMPONENT_SWIZZLE_G: return colors[1];
case VK_COMPONENT_SWIZZLE_B: return colors[2];
case VK_COMPONENT_SWIZZLE_A: return colors[3];
default: return colors[index];
}
}
#pragma mark Mipmaps #pragma mark Mipmaps