Merge pull request #1955 from cdavis5e/4444-formats
Support the `VK_EXT_4444_formats` extension.
This commit is contained in:
commit
591eb6bdaa
@ -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`
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;"];
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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 ||
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user