Merge pull request #867 from billhollings/master

MVKPixelFormats enables atomic capabilities only when applicable.
This commit is contained in:
Bill Hollings 2020-04-23 14:30:39 -04:00 committed by GitHub
commit e39925f5ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 80 deletions

View File

@ -44,12 +44,13 @@ typedef enum : uint16_t {
kMVKMTLFmtCapsRead = (1<<0),
kMVKMTLFmtCapsFilter = (1<<1),
kMVKMTLFmtCapsWrite = (1<<2),
kMVKMTLFmtCapsColorAtt = (1<<3),
kMVKMTLFmtCapsDSAtt = (1<<4),
kMVKMTLFmtCapsBlend = (1<<5),
kMVKMTLFmtCapsMSAA = (1<<6),
kMVKMTLFmtCapsResolve = (1<<7),
kMVKMTLFmtCapsVertex = (1<<8),
kMVKMTLFmtCapsAtomic = (1<<3),
kMVKMTLFmtCapsColorAtt = (1<<4),
kMVKMTLFmtCapsDSAtt = (1<<5),
kMVKMTLFmtCapsBlend = (1<<6),
kMVKMTLFmtCapsMSAA = (1<<7),
kMVKMTLFmtCapsResolve = (1<<8),
kMVKMTLFmtCapsVertex = (1<<9),
kMVKMTLFmtCapsRF = (kMVKMTLFmtCapsRead | kMVKMTLFmtCapsFilter),
kMVKMTLFmtCapsRC = (kMVKMTLFmtCapsRead | kMVKMTLFmtCapsColorAtt),
@ -291,14 +292,12 @@ protected:
MVKMTLFormatDesc& getMTLPixelFormatDesc(MTLPixelFormat mtlFormat);
MVKMTLFormatDesc& getMTLVertexFormatDesc(VkFormat vkFormat);
MVKMTLFormatDesc& getMTLVertexFormatDesc(MTLVertexFormat mtlFormat);
VkFormatFeatureFlags getOptimalTilingFeatures(VkFormat vkFormat, MVKMTLFmtCaps mtlFmtCaps);
VkFormatFeatureFlags getLinearTilingFeatures(VkFormat vkFormat, MVKMTLFmtCaps mtlFmtCaps, MVKFormatType mvkFmtType);
VkFormatFeatureFlags getBufferFeatures(VkFormat vkFormat, MVKMTLFmtCaps mtlFmtTexCaps, MVKMTLFmtCaps mtlFmtVtxCaps, MVKFormatType mvkFmtType);
void initVkFormatCapabilities();
void initMTLPixelFormatCapabilities();
void initMTLVertexFormatCapabilities();
void buildMTLFormatMaps();
void buildVkFormatMaps();
void setFormatProperties(MVKVkFormatDesc& vkDesc);
void modifyMTLFormatCapabilities();
void modifyMTLFormatCapabilities(id<MTLDevice> mtlDevice);
void addMTLPixelFormatCapabilities(id<MTLDevice> mtlDevice,

View File

@ -1072,6 +1072,10 @@ void MVKPixelFormats::modifyMTLFormatCapabilities() {
// Modifies the format capability tables based on the capabilities of the specific MTLDevice
#if MVK_MACOS
void MVKPixelFormats::modifyMTLFormatCapabilities(id<MTLDevice> mtlDevice) {
addMTLPixelFormatCapabilities( macOS_GPUFamily1_v1, R32Uint, Atomic );
addMTLPixelFormatCapabilities( macOS_GPUFamily1_v1, R32Sint, Atomic );
if (mtlDevice.isDepth24Stencil8PixelFormatSupported) {
addMTLPixelFormatCapabilities( macOS_GPUFamily1_v1, Depth24Unorm_Stencil8, DRFMR );
}
@ -1105,7 +1109,9 @@ void MVKPixelFormats::modifyMTLFormatCapabilities(id<MTLDevice> mtlDevice) {
addMTLPixelFormatCapabilities( iOS_GPUFamily2_v1, RG8Snorm, All );
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Uint, RWC );
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Uint, Atomic );
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Sint, RWC );
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Sint, Atomic );
addMTLPixelFormatCapabilities( iOS_GPUFamily1_v2, R32Float, RWCMB );
@ -1227,13 +1233,8 @@ void MVKPixelFormats::buildVkFormatMaps() {
if ( !mtlDesc.isSupported() ) { vkDesc.mtlVertexFormatSubstitute = MTLVertexFormatInvalid; }
}
// Vulkan format features
MVKFormatType fmtType = vkDesc.formatType;
MVKMTLFmtCaps mtlPixFmtCaps = getMTLPixelFormatDesc(vkFmt).mtlFmtCaps;
MVKMTLFmtCaps mtlVtxFmtCaps = getMTLVertexFormatDesc(vkFmt).mtlFmtCaps;
vkDesc.properties = { getLinearTilingFeatures(vkFmt, mtlPixFmtCaps, fmtType),
getOptimalTilingFeatures(vkFmt, mtlPixFmtCaps),
getBufferFeatures(vkFmt, mtlPixFmtCaps, mtlVtxFmtCaps, fmtType) };
// Set Vulkan format properties
setFormatProperties(vkDesc);
}
}
}
@ -1246,87 +1247,65 @@ typedef enum : VkFormatFeatureFlags {
VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
VK_FORMAT_FEATURE_BLIT_SRC_BIT),
kMVKVkFormatFeatureFlagsTexFilter = (VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT),
kMVKVkFormatFeatureFlagsTexWrite = (VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT),
kMVKVkFormatFeatureFlagsTexWrite = (VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT),
kMVKVkFormatFeatureFlagsTexAtomic = (VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT),
kMVKVkFormatFeatureFlagsTexColorAtt = (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_BLIT_DST_BIT),
kMVKVkFormatFeatureFlagsTexDSAtt = (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT),
kMVKVkFormatFeatureFlagsTexBlend = (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
kMVKVkFormatFeatureFlagsBufRead = (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT),
kMVKVkFormatFeatureFlagsBufWrite = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT |
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT),
kMVKVkFormatFeatureFlagsBufWrite = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT),
kMVKVkFormatFeatureFlagsBufAtomic = (VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT),
kMVKVkFormatFeatureFlagsBufVertex = (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT),
} MVKVkFormatFeatureFlags;
#define enableTexFormatFeatures(CAP) \
if (mvkAreAllFlagsEnabled(mtlFmtCaps, kMVKMTLFmtCaps ##CAP)) { \
vkFeatures |= kMVKVkFormatFeatureFlagsTex ##CAP; \
}
VkFormatFeatureFlags MVKPixelFormats::getOptimalTilingFeatures(VkFormat vkFormat,
MVKMTLFmtCaps mtlFmtCaps) {
VkFormatFeatureFlags vkFeatures = kMVKVkFormatFeatureFlagsTexNone;
enableTexFormatFeatures(Read);
enableTexFormatFeatures(Filter);
enableTexFormatFeatures(Write);
enableTexFormatFeatures(ColorAtt);
enableTexFormatFeatures(DSAtt);
enableTexFormatFeatures(Blend);
// Only support atomics on R32UI/R32I images for now. Until Metal supports this
// for real, we need to use the underlying buffer to support image atomics.
if (vkFormat != VK_FORMAT_R32_UINT && vkFormat != VK_FORMAT_R32_SINT) {
mvkDisableFlags(vkFeatures, VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT);
}
return vkFeatures;
}
// Sets the VkFormatProperties (optimal/linear/buffer) for the Vulkan format.
void MVKPixelFormats::setFormatProperties(MVKVkFormatDesc& vkDesc) {
VkFormatFeatureFlags MVKPixelFormats::getLinearTilingFeatures(VkFormat vkFormat,
MVKMTLFmtCaps mtlFmtCaps,
MVKFormatType mvkFmtType) {
// Depth-stencil or compressed formats cannot be used for linear textures.
if (mvkFmtType == kMVKFormatDepthStencil || mvkFmtType == kMVKFormatCompressed) {
return kMVKVkFormatFeatureFlagsTexNone;
# define enableFormatFeatures(CAP, TYPE, MTL_FMT_CAPS, VK_FEATS) \
if (mvkAreAllFlagsEnabled(MTL_FMT_CAPS, kMVKMTLFmtCaps ##CAP)) { \
mvkEnableFlags(VK_FEATS, kMVKVkFormatFeatureFlags ##TYPE ##CAP); \
}
// Start with the optimal features.
VkFormatFeatureFlags vkFeatures = getOptimalTilingFeatures(vkFormat, mtlFmtCaps);
VkFormat vkFmt = vkDesc.vkFormat;
VkFormatProperties& vkProps = vkDesc.properties;
MVKMTLFmtCaps mtlPixFmtCaps = getMTLPixelFormatDesc(vkFmt).mtlFmtCaps;
// Set optimal tiling features first
vkProps.optimalTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
enableFormatFeatures(Read, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
enableFormatFeatures(Filter, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
enableFormatFeatures(Write, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
enableFormatFeatures(ColorAtt, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
enableFormatFeatures(DSAtt, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
enableFormatFeatures(Blend, Tex, mtlPixFmtCaps, vkProps.optimalTilingFeatures);
// Linear tiling is not available to depth/stencil or compressed formats.
vkProps.linearTilingFeatures = kMVKVkFormatFeatureFlagsTexNone;
if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed) ) {
// Start with optimal tiling features, and modify.
vkProps.linearTilingFeatures = vkProps.optimalTilingFeatures;
// Linear tiling can support atomic writing for some formats, even though optimal tiling does not.
enableFormatFeatures(Atomic, Tex, mtlPixFmtCaps, vkProps.linearTilingFeatures);
#if MVK_MACOS
// On macOS, linear textures cannot be used as attachments, so disable those features.
mvkDisableFlags(vkFeatures, (kMVKVkFormatFeatureFlagsTexColorAtt |
kMVKVkFormatFeatureFlagsTexDSAtt |
kMVKVkFormatFeatureFlagsTexBlend));
// On macOS, linear textures cannot be used as attachments, so disable those features.
mvkDisableFlags(vkProps.linearTilingFeatures, (kMVKVkFormatFeatureFlagsTexColorAtt |
kMVKVkFormatFeatureFlagsTexDSAtt |
kMVKVkFormatFeatureFlagsTexBlend));
#endif
return vkFeatures;
}
VkFormatFeatureFlags MVKPixelFormats::getBufferFeatures(VkFormat vkFormat,
MVKMTLFmtCaps mtlPixFmtCaps,
MVKMTLFmtCaps mtlVtxFmtCaps,
MVKFormatType mvkFmtType) {
// Depth-stencil or compressed formats cannot be used for texel buffers.
if (mvkFmtType == kMVKFormatDepthStencil || mvkFmtType == kMVKFormatCompressed) {
return kMVKVkFormatFeatureFlagsTexNone;
}
VkFormatFeatureFlags vkFeatures = kMVKVkFormatFeatureFlagsTexNone;
if (mvkAreAllFlagsEnabled(mtlPixFmtCaps, kMVKMTLFmtCapsRead)) {
vkFeatures |= kMVKVkFormatFeatureFlagsBufRead;
// Texel buffers are not available to depth/stencil or compressed formats.
vkProps.bufferFeatures = kMVKVkFormatFeatureFlagsTexNone;
if ( !(vkDesc.formatType == kMVKFormatDepthStencil || vkDesc.formatType == kMVKFormatCompressed) ) {
enableFormatFeatures(Read, Buf, mtlPixFmtCaps, vkProps.bufferFeatures);
enableFormatFeatures(Write, Buf, mtlPixFmtCaps, vkProps.bufferFeatures);
enableFormatFeatures(Atomic, Buf, mtlPixFmtCaps, vkProps.bufferFeatures);
enableFormatFeatures(Vertex, Buf, getMTLVertexFormatDesc(vkFmt).mtlFmtCaps, vkProps.bufferFeatures);
}
if (mvkAreAllFlagsEnabled(mtlPixFmtCaps, kMVKMTLFmtCapsWrite)) {
vkFeatures |= kMVKVkFormatFeatureFlagsBufWrite;
}
if (mvkAreAllFlagsEnabled(mtlVtxFmtCaps, kMVKMTLFmtCapsVertex)) {
vkFeatures |= kMVKVkFormatFeatureFlagsBufVertex;
}
// Only support atomics on R32UI/R32I images for now. Until Metal supports this
// for real, we need to use the underlying buffer to support image atomics.
if (vkFormat != VK_FORMAT_R32_UINT && vkFormat != VK_FORMAT_R32_SINT) {
mvkDisableFlags(vkFeatures, VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT);
}
return vkFeatures;
}