Merge pull request #2142 from cdavis5e/metal-spis

Add more Metal SPI support
This commit is contained in:
Bill Hollings 2024-01-29 19:49:12 -05:00 committed by GitHub
commit 224b14a080
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 444 additions and 25 deletions

View File

@ -125,6 +125,19 @@ extern "C" {
(__IPHONE_OS_VERSION_MAX_ALLOWED >= 140000))
#endif
/**
* Enable use of private Metal APIs.
*
* Enabling this build setting during a MoltenVK build will allow MoltenVK to
* extend its functionality by using certain private Metal API calls, but it
* will also disqualify the app from being distributed via Apple App Stores.
*
* Disabled by default.
*/
#ifndef MVK_USE_METAL_PRIVATE_API
# define MVK_USE_METAL_PRIVATE_API 0
#endif
/** Directive to identify public symbols. */
#define MVK_PUBLIC_SYMBOL __attribute__((visibility("default"))) __attribute__((used))

View File

@ -663,3 +663,16 @@ Determines the style used to implement _Vulkan_ semaphore (`VkSemaphore`) functi
In the special case of `VK_SEMAPHORE_TYPE_TIMELINE` semaphores, **MoltenVK** will always use
`MTLSharedEvent` if it is available on the platform, regardless of the value of this parameter.
---------------------------------------
#### MVK_CONFIG_USE_METAL_PRIVATE_API
##### Type: Boolean
##### Default: Value of `MVK_USE_METAL_PRIVATE_API`
If enabled, **MoltenVK** will _use_ private interfaces exposed by _Metal_ to implement _Vulkan_
features that are difficult to support otherwise.
Unlike `MVK_USE_METAL_PRIVATE_API`, this setting may be overridden at run time.
This option is not available unless MoltenVK were built with `MVK_USE_METAL_PRIVATE_API` set to `1`.

View File

@ -20,6 +20,10 @@ Released TBD
- Add `MVK_USE_METAL_PRIVATE_API` build setting to allow **MoltenVK** to be built with access to _Metal_ private API calls.
- Add support for `VkPhysicalDeviceFeatures::wideLines` feature when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build.
- Add support for the `VkPhysicalDeviceFeatures::logicOp` feature when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build.
- Add support for the `VkPhysicalDeviceFeatures::depthBounds` feature on AMD GPUs when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build.
- Add support for the `VkPhysicalDevicePortabilitySubsetFeaturesKHR::samplerMipLodBias` feature when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build.
- Add support for Metal native pipeline sample masks when `MVK_USE_METAL_PRIVATE_API` is enabled in a **MoltenVK** build.
- Fix potential crash when using multi-planar images.
- Ensure buffers available for buffer addresses in push constants.
- Support `libMoltenVK.dylib` for _iOS Simulator_ architecture.

View File

@ -140,6 +140,10 @@
45557A5321C9EFF3008868BD /* MVKCodec.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45557A4D21C9EFF3008868BD /* MVKCodec.mm */; };
45557A5421C9EFF3008868BD /* MVKCodec.h in Headers */ = {isa = PBXBuildFile; fileRef = 45557A5121C9EFF3008868BD /* MVKCodec.h */; };
45557A5521C9EFF3008868BD /* MVKCodec.h in Headers */ = {isa = PBXBuildFile; fileRef = 45557A5121C9EFF3008868BD /* MVKCodec.h */; };
45E3A40B2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 45E3A4062166B922005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h */; };
45E3A40C2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 45E3A4062166B922005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h */; };
45E3A40D2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 45E3A40A2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m */; };
45E3A40E2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = 45E3A40A2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m */; };
A9096E5E1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9096E5D1F81E16300DFBEA6 /* MVKCmdDispatch.mm */; };
A9096E5F1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9096E5D1F81E16300DFBEA6 /* MVKCmdDispatch.mm */; };
A909F65F213B190700FCD6BE /* MVKExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A909F65A213B190600FCD6BE /* MVKExtensions.h */; };
@ -582,6 +586,8 @@
45557A4D21C9EFF3008868BD /* MVKCodec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCodec.mm; sourceTree = "<group>"; };
45557A5121C9EFF3008868BD /* MVKCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCodec.h; sourceTree = "<group>"; };
45557A5721CD83C3008868BD /* MVKDXTnCodec.def */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = MVKDXTnCodec.def; sourceTree = "<group>"; };
45E3A4062166B922005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h"; sourceTree = "<group>"; };
45E3A40A2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m"; sourceTree = "<group>"; };
A9096E5C1F81E16300DFBEA6 /* MVKCmdDispatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVKCmdDispatch.h; sourceTree = "<group>"; };
A9096E5D1F81E16300DFBEA6 /* MVKCmdDispatch.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCmdDispatch.mm; sourceTree = "<group>"; };
A909F65A213B190600FCD6BE /* MVKExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKExtensions.h; sourceTree = "<group>"; };
@ -904,6 +910,8 @@
453638302508A4C6000EFFD3 /* MTLRenderPassStencilAttachmentDescriptor+MoltenVK.m */,
A9E53DFE21064F84002781DD /* MTLRenderPipelineDescriptor+MoltenVK.h */,
A9E53DFA21064F84002781DD /* MTLRenderPipelineDescriptor+MoltenVK.m */,
45E3A4062166B922005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h */,
45E3A40A2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m */,
A9E53DD32100B197002781DD /* MTLSamplerDescriptor+MoltenVK.h */,
A9E53DCD2100B197002781DD /* MTLSamplerDescriptor+MoltenVK.m */,
A9E53DD02100B197002781DD /* MTLTextureDescriptor+MoltenVK.h */,
@ -1086,6 +1094,7 @@
A94FB7BC1C7DFB4800632CA3 /* MVKCmdPipeline.h in Headers */,
A9F3D9DC24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */,
A9C327562AAFBD390025EE79 /* MVKConfigMembers.def in Headers */,
45E3A40B2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h in Headers */,
A94FB7F81C7DFB4800632CA3 /* MVKPipeline.h in Headers */,
A94FB7F01C7DFB4800632CA3 /* MVKImage.h in Headers */,
4553AEFD2251617100E8EBCD /* MVKBlockObserver.h in Headers */,
@ -1163,6 +1172,7 @@
A94FB7C51C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */,
A94FB7BD1C7DFB4800632CA3 /* MVKCmdPipeline.h in Headers */,
A9F3D9DD24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */,
45E3A40C2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h in Headers */,
A94FB7F91C7DFB4800632CA3 /* MVKPipeline.h in Headers */,
A9C327582AAFBD3A0025EE79 /* MVKConfigMembers.def in Headers */,
A94FB7F11C7DFB4800632CA3 /* MVKImage.h in Headers */,
@ -1776,6 +1786,7 @@
A9E53DE92100B197002781DD /* CAMetalLayer+MoltenVK.mm in Sources */,
A9096E5E1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */,
A99C90F0229455B300A061DA /* MVKCmdDebug.mm in Sources */,
45E3A40D2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1836,6 +1847,7 @@
A9E53DEA2100B197002781DD /* CAMetalLayer+MoltenVK.mm in Sources */,
A9096E5F1F81E16300DFBEA6 /* MVKCmdDispatch.mm in Sources */,
A99C90F1229455B300A061DA /* MVKCmdDebug.mm in Sources */,
45E3A40E2166B923005E3E38 /* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -342,6 +342,9 @@ MTLBlendOperation mvkMTLBlendOperationFromVkBlendOp(VkBlendOp vkBlendOp);
/** Returns the Metal MTLBlendFactor corresponding to the specified Vulkan VkBlendFactor. */
MTLBlendFactor mvkMTLBlendFactorFromVkBlendFactor(VkBlendFactor vkBlendFactor);
/** Returns the Metal MTLLogicOperation corresponding to the specified Vulkan VkLogicOp. */
NSUInteger mvkMTLLogicOperationFromVkLogicOp(VkLogicOp vkBlendOp);
/**
* Returns the Metal MTLVertexFormat corresponding to the specified
* Vulkan VkFormat as used as a vertex attribute format.

View File

@ -240,6 +240,8 @@ typedef struct {
MVKConfigCompressionAlgorithm shaderSourceCompressionAlgorithm; /**< MVK_CONFIG_SHADER_COMPRESSION_ALGORITHM */
VkBool32 shouldMaximizeConcurrentCompilation; /**< MVK_CONFIG_SHOULD_MAXIMIZE_CONCURRENT_COMPILATION */
float timestampPeriodLowPassAlpha; /**< MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA */
VkBool32 useMetalPrivateAPI; /**< MVK_CONFIG_USE_METAL_PRIVATE_API */
uint32_t _unused_struct_padding;
} MVKConfiguration;
// Legacy support for renamed struct elements.

View File

@ -375,6 +375,41 @@ protected:
};
#pragma mark -
#pragma mark MVKCmdSetDepthBounds
/** Vulkan command to set depth bounds. */
class MVKCmdSetDepthBounds : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
float minDepthBounds,
float maxDepthBounds);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
float _minDepthBounds;
float _maxDepthBounds;
};
#pragma mark -
#pragma mark MVKCmdSetDepthBoundsTestEnable
/** Vulkan command to enable depth bounds testing. */
class MVKCmdSetDepthBoundsTestEnable : public MVKSingleValueCommand<VkBool32> {
public:
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
};
#pragma mark -
#pragma mark MVKCmdSetStencilTestEnable

View File

@ -327,6 +327,30 @@ void MVKCmdSetDepthCompareOp::encode(MVKCommandEncoder* cmdEncoder) {
}
#pragma mark -
#pragma mark MVKCmdSetDepthBounds
VkResult MVKCmdSetDepthBounds::setContent(MVKCommandBuffer* cmdBuff,
float minDepthBounds,
float maxDepthBounds) {
_minDepthBounds = minDepthBounds;
_maxDepthBounds = maxDepthBounds;
return VK_SUCCESS;
}
void MVKCmdSetDepthBounds::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_renderingState.setDepthBounds(_minDepthBounds, _maxDepthBounds, true);
}
#pragma mark -
#pragma mark MVKCmdSetDepthBoundsTestEnable
void MVKCmdSetDepthBoundsTestEnable::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_renderingState.setDepthBoundsTestEnable(_value, true);
}
#pragma mark -
#pragma mark MVKCmdSetStencilTestEnable

View File

@ -239,6 +239,11 @@ struct MVKDepthBias {
float depthBiasClamp;
};
struct MVKDepthBounds {
float minDepthBound;
float maxDepthBound;
};
struct MVKStencilReference {
uint32_t frontFaceValue;
uint32_t backFaceValue;
@ -272,6 +277,8 @@ public:
void setDepthBiasEnable(VkBool32 depthBiasEnable);
void setDepthClipEnable(bool depthClip, bool isDynamic);
void setDepthBounds(float minDepthBounds, float maxDepthBounds, bool isDynamic);
void setDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable, bool isDynamic);
void setStencilReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
void setStencilReferenceValues(VkStencilFaceFlags faceMask, uint32_t stencilReference);
@ -318,6 +325,7 @@ protected:
MVKMTLScissors _mtlScissors[StateScope::Count] = {};
MVKColor32 _mtlBlendConstants[StateScope::Count] = {};
MVKDepthBias _mtlDepthBias[StateScope::Count] = {};
MVKDepthBounds _mtlDepthBounds[StateScope::Count] = {};
MVKStencilReference _mtlStencilReference[StateScope::Count] = {};
MTLCullMode _mtlCullMode[StateScope::Count] = { MTLCullModeNone, MTLCullModeNone };
MTLWinding _mtlFrontFace[StateScope::Count] = { MTLWindingClockwise, MTLWindingClockwise };
@ -332,6 +340,7 @@ protected:
bool _mtlDepthBiasEnable[StateScope::Count] = {};
bool _mtlPrimitiveRestartEnable[StateScope::Count] = {};
bool _mtlRasterizerDiscardEnable[StateScope::Count] = {};
bool _mtlDepthBoundsTestEnable[StateScope::Count] = {};
bool _cullBothFaces[StateScope::Count] = {};
bool _isPolygonModePoint[StateScope::Count] = {};
};

View File

@ -369,6 +369,16 @@ void MVKRenderingCommandEncoderState::setDepthClipEnable(bool depthClip, bool is
setMTLContent(DepthClipEnable);
}
void MVKRenderingCommandEncoderState::setDepthBounds(float minDepthBounds, float maxDepthBounds, bool isDynamic) {
MVKDepthBounds mtlDepthBounds = { minDepthBounds, maxDepthBounds };
setMTLContent(DepthBounds);
}
void MVKRenderingCommandEncoderState::setDepthBoundsTestEnable(VkBool32 depthBoundsTestEnable, bool isDynamic) {
auto mtlDepthBoundsTestEnable = static_cast<bool>(depthBoundsTestEnable);
setMTLContent(DepthBoundsTestEnable);
}
void MVKRenderingCommandEncoderState::setStencilReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
bool isDynamic = false;
MVKStencilReference mtlStencilReference = {
@ -545,6 +555,14 @@ bool MVKRenderingCommandEncoderState::needsMetalRenderPassRestart() {
// An extension of the MTLRenderCommandEncoder protocol to declare the setLineWidth: method.
@protocol MVKMTLRenderCommandEncoderLineWidth <MTLRenderCommandEncoder>
-(void) setLineWidth: (float) width;
@end
// An extension of the MTLRenderCommandEncoder protocol containing a declaration of the
// -setDepthBoundsTestAMD:minDepth:maxDepth: method.
@protocol MVKMTLRenderCommandEncoderDepthBoundsAMD <MTLRenderCommandEncoder>
- (void)setDepthBoundsTestAMD:(BOOL)enable minDepth:(float)minDepth maxDepth:(float)maxDepth;
@end
#endif
@ -584,6 +602,21 @@ void MVKRenderingCommandEncoderState::encodeImpl(uint32_t stage) {
[rendEnc setDepthClipMode: getMTLContent(DepthClipEnable)];
}
#if MVK_USE_METAL_PRIVATE_API
if (getMVKConfig().useMetalPrivateAPI && (isDirty(DepthBoundsTestEnable) || isDirty(DepthBounds)) &&
_cmdEncoder->_pDeviceFeatures->depthBounds) {
if (getMTLContent(DepthBoundsTestEnable)) {
auto& db = getMTLContent(DepthBounds);
[(id<MVKMTLRenderCommandEncoderDepthBoundsAMD>)_cmdEncoder->_mtlRenderEncoder setDepthBoundsTestAMD: YES
minDepth: db.minDepthBound
maxDepth: db.maxDepthBound];
} else {
[(id<MVKMTLRenderCommandEncoderDepthBoundsAMD>)_cmdEncoder->_mtlRenderEncoder setDepthBoundsTestAMD: NO
minDepth: 0.0f
maxDepth: 1.0f];
}
}
#endif
if (isDirty(StencilReference)) {
auto& sr = getMTLContent(StencilReference);
[rendEnc setStencilFrontReferenceValue: sr.frontFaceValue backReferenceValue: sr.backFaceValue];

View File

@ -90,6 +90,8 @@ MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetScissor, 1)
MVK_CMD_TYPE_POOL(SetBlendConstants)
MVK_CMD_TYPE_POOL(SetDepthBias)
MVK_CMD_TYPE_POOL(SetDepthBiasEnable)
MVK_CMD_TYPE_POOL(SetDepthBounds)
MVK_CMD_TYPE_POOL(SetDepthBoundsTestEnable)
MVK_CMD_TYPE_POOL(SetDepthTestEnable)
MVK_CMD_TYPE_POOL(SetDepthWriteEnable)
MVK_CMD_TYPE_POOL(SetDepthClipEnable)

View File

@ -366,7 +366,7 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
portabilityFeatures->multisampleArrayImage = _metalFeatures.multisampleArrayTextures;
portabilityFeatures->mutableComparisonSamplers = _metalFeatures.depthSampleCompare;
portabilityFeatures->pointPolygons = false;
portabilityFeatures->samplerMipLodBias = false;
portabilityFeatures->samplerMipLodBias = getMVKConfig().useMetalPrivateAPI;
portabilityFeatures->separateStencilMaskRef = true;
portabilityFeatures->shaderSampleRateInterpolationFunctions = _metalFeatures.pullModelInterpolation;
portabilityFeatures->tessellationIsolines = false;
@ -2338,10 +2338,11 @@ void MVKPhysicalDevice::initFeatures() {
_features.fullDrawIndexUint32 = true;
_features.independentBlend = true;
_features.sampleRateShading = true;
_features.logicOp = getMVKConfig().useMetalPrivateAPI;
_features.depthBiasClamp = true;
_features.fillModeNonSolid = true;
_features.largePoints = true;
_features.wideLines = static_cast<bool>(MVK_USE_METAL_PRIVATE_API);
_features.wideLines = getMVKConfig().useMetalPrivateAPI;
_features.alphaToOne = true;
_features.samplerAnisotropy = true;
_features.shaderImageGatherExtended = true;
@ -2442,6 +2443,13 @@ void MVKPhysicalDevice::initFeatures() {
_features.shaderStorageImageArrayDynamicIndexing = _metalFeatures.arrayOfTextures;
#if MVK_USE_METAL_PRIVATE_API
if (getMVKConfig().useMetalPrivateAPI && _properties.vendorID == kAMDVendorId) {
// Only AMD drivers have the method we need for now.
_features.depthBounds = true;
}
#endif
if (supportsMTLFeatureSet(macOS_GPUFamily1_v2)) {
_features.tessellationShader = true;
_features.dualSrcBlend = true;
@ -2522,6 +2530,10 @@ void MVKPhysicalDevice::initLimits() {
_properties.limits.maxImageDimension3D = _metalFeatures.maxTextureLayers;
_properties.limits.maxImageArrayLayers = _metalFeatures.maxTextureLayers;
// Max sum of API and shader values. Bias not publicly supported in API, but can be applied in the shader directly.
// The lack of API value is covered by VkPhysicalDevicePortabilitySubsetFeaturesKHR::samplerMipLodBias.
// Metal does not specify a limit for the shader value, so choose something reasonable.
_properties.limits.maxSamplerLodBias = getMVKConfig().useMetalPrivateAPI ? 16 : 4;
_properties.limits.maxSamplerAnisotropy = 16;
_properties.limits.maxVertexInputAttributes = 31;
@ -2798,11 +2810,6 @@ void MVKPhysicalDevice::initLimits() {
#endif
}
// Max sum of API and shader values. Bias not supported in API, but can be applied in shader directly.
// The lack of API value is covered by VkPhysicalDevicePortabilitySubsetFeaturesKHR::samplerMipLodBias.
// Metal does not specify limit for shader value, so choose something reasonable.
_properties.limits.maxSamplerLodBias = 4;
_properties.limits.minTexelOffset = -8;
_properties.limits.maxTexelOffset = 7;
_properties.limits.minTexelGatherOffset = _properties.limits.minTexelOffset;

View File

@ -2221,6 +2221,11 @@ MTLSamplerDescriptor* MVKSampler::newMTLSamplerDescriptor(const VkSamplerCreateI
mtlSampDesc.mipFilter = (pCreateInfo->unnormalizedCoordinates
? MTLSamplerMipFilterNotMipmapped
: mvkMTLSamplerMipFilterFromVkSamplerMipmapMode(pCreateInfo->mipmapMode));
#if MVK_USE_METAL_PRIVATE_API
if (getMVKConfig().useMetalPrivateAPI) {
mtlSampDesc.lodBiasMVK = pCreateInfo->mipLodBias;
}
#endif
mtlSampDesc.lodMinClamp = pCreateInfo->minLod;
mtlSampDesc.lodMaxClamp = pCreateInfo->maxLod;
mtlSampDesc.maxAnisotropy = (pCreateInfo->anisotropyEnable

View File

@ -23,6 +23,9 @@
#include "MVKOSExtensions.h"
#include "MVKStrings.h"
#include "MTLRenderPipelineDescriptor+MoltenVK.h"
#if MVK_USE_METAL_PRIVATE_API
#include "MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h"
#endif
#include "mvk_datatypes.hpp"
#ifndef MVK_USE_CEREAL
@ -304,6 +307,9 @@ void MVKGraphicsPipeline::encode(MVKCommandEncoder* cmdEncoder, uint32_t stage)
cmdEncoder->_renderingState.setPrimitiveTopology(_vkPrimitiveTopology, false);
cmdEncoder->_renderingState.setPrimitiveRestartEnable(_primitiveRestartEnable, false);
cmdEncoder->_renderingState.setBlendConstants(_blendConstants, false);
if (_device->_enabledFeatures.depthBounds) {
cmdEncoder->_renderingState.setDepthBounds(_depthStencilInfo.minDepthBounds, _depthStencilInfo.maxDepthBounds, false);
}
cmdEncoder->_renderingState.setStencilReferenceValues(_depthStencilInfo);
cmdEncoder->_renderingState.setViewports(_viewports.contents(), 0, false);
cmdEncoder->_renderingState.setScissors(_scissors.contents(), 0, false);
@ -1299,9 +1305,15 @@ bool MVKGraphicsPipeline::addFragmentShaderToPipeline(MTLRenderPipelineDescripto
shaderConfig.options.mslOptions.sample_dref_lod_array_as_grad = true;
}
if (_isRasterizing && pCreateInfo->pMultisampleState) { // Must ignore allowed bad pMultisampleState pointer if rasterization disabled
if (pCreateInfo->pMultisampleState->pSampleMask && pCreateInfo->pMultisampleState->pSampleMask[0] != 0xffffffff) {
shaderConfig.options.mslOptions.additional_fixed_sample_mask = pCreateInfo->pMultisampleState->pSampleMask[0];
#if MVK_USE_METAL_PRIVATE_API
if (!getMVKConfig().useMetalPrivateAPI) {
#endif
if (pCreateInfo->pMultisampleState->pSampleMask && pCreateInfo->pMultisampleState->pSampleMask[0] != 0xffffffff) {
shaderConfig.options.mslOptions.additional_fixed_sample_mask = pCreateInfo->pMultisampleState->pSampleMask[0];
}
#if MVK_USE_METAL_PRIVATE_API
}
#endif
shaderConfig.options.mslOptions.force_sample_rate_shading = pCreateInfo->pMultisampleState->sampleShadingEnable && pCreateInfo->pMultisampleState->minSampleShading != 0.0f;
}
if (std::any_of(shaderOutputs.begin(), shaderOutputs.end(), [](const SPIRVShaderOutput& output) { return output.builtin == spv::BuiltInLayer; })) {
@ -1616,6 +1628,12 @@ void MVKGraphicsPipeline::addFragmentOutputToPipeline(MTLRenderPipelineDescripto
colorDesc.alphaBlendOperation = mvkMTLBlendOperationFromVkBlendOp(pCA->alphaBlendOp);
colorDesc.sourceAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->srcAlphaBlendFactor);
colorDesc.destinationAlphaBlendFactor = mvkMTLBlendFactorFromVkBlendFactor(pCA->dstAlphaBlendFactor);
#if MVK_USE_METAL_PRIVATE_API
if (getMVKConfig().useMetalPrivateAPI) {
colorDesc.logicOpEnabledMVK = pCreateInfo->pColorBlendState->logicOpEnable;
colorDesc.logicOpMVK = mvkMTLLogicOperationFromVkLogicOp(pCreateInfo->pColorBlendState->logicOp);
}
#endif
}
}
}
@ -1642,6 +1660,11 @@ void MVKGraphicsPipeline::addFragmentOutputToPipeline(MTLRenderPipelineDescripto
// Multisampling - must ignore allowed bad pMultisampleState pointer if rasterization disabled
if (_isRasterizing && pCreateInfo->pMultisampleState) {
plDesc.rasterSampleCount = mvkSampleCountFromVkSampleCountFlagBits(pCreateInfo->pMultisampleState->rasterizationSamples);
#if MVK_USE_METAL_PRIVATE_API
if (getMVKConfig().useMetalPrivateAPI && pCreateInfo->pMultisampleState->pSampleMask) {
plDesc.sampleMaskMVK = pCreateInfo->pMultisampleState->pSampleMask[0];
}
#endif
plDesc.alphaToCoverageEnabled = pCreateInfo->pMultisampleState->alphaToCoverageEnable;
plDesc.alphaToOneEnabled = pCreateInfo->pMultisampleState->alphaToOneEnable;

View File

@ -0,0 +1,46 @@
/*
* MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h
*
* Copyright (c) 2018-2023 Chip Davis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#import <Metal/Metal.h>
/** Extensions to MTLRenderPipelineColorAttachmentDescriptor to support MoltenVK. */
@interface MTLRenderPipelineColorAttachmentDescriptor (MoltenVK)
/**
* Replacement for the logicOpEnabled property.
*
* This property allows support under all OS versions. Delegates to the logicOpEnabled
* property if it is available. otherwise, returns NO when read and does nothing when set.
*/
@property(nonatomic, readwrite, getter=isLogicOpEnabledMVK) BOOL logicOpEnabledMVK;
/**
* Replacement for the logicOp property.
*
* This property allows support under all OS versions. Delegates to the logicOp
* property if it is available. otherwise, returns MTLLogicOperationCopy when
* read and does nothing when set.
*
* The value is treated as an NSUInteger to support OS versions on which the enum is unavailable.
*/
@property(nonatomic, readwrite) NSUInteger logicOpMVK;
@end

View File

@ -0,0 +1,67 @@
/*
* MTLRenderPipelineDescriptor+MoltenVK.m
*
* Copyright (c) 2018-2023 Chip Davis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "MVKCommonEnvironment.h"
#if MVK_USE_METAL_PRIVATE_API
#include "MTLRenderPipelineDescriptor+MoltenVK.h"
typedef NSUInteger MTLLogicOperation;
@interface MTLRenderPipelineColorAttachmentDescriptor ()
- (BOOL)isLogicOpEnabled;
- (void)setLogicOpEnabled: (BOOL)enable;
- (MTLLogicOperation)logicOp;
- (void)setLogicOp: (MTLLogicOperation)op;
@end
@implementation MTLRenderPipelineColorAttachmentDescriptor (MoltenVK)
- (BOOL)isLogicOpEnabledMVK {
if ([self respondsToSelector:@selector(isLogicOpEnabled)]) {
return [self isLogicOpEnabled];
}
return NO;
}
- (void)setLogicOpEnabledMVK: (BOOL)enable {
if ([self respondsToSelector:@selector(setLogicOpEnabled:)]) {
[self setLogicOpEnabled: enable];
}
}
- (NSUInteger)logicOpMVK {
if ([self respondsToSelector:@selector(logicOp)]) {
return [self logicOp];
}
return 3 /* MTLLogicOperationCopy */;
}
- (void)setLogicOpMVK: (MTLLogicOperation)op {
if ([self respondsToSelector:@selector(setLogicOp:)]) {
[self setLogicOp: (MTLLogicOperation)op];
}
}
@end
#endif /* MVK_CONFIG_SUPPORT_METAL_SPIS */

View File

@ -33,4 +33,13 @@
*/
@property(nonatomic, readwrite) MTLPrimitiveTopologyClass inputPrimitiveTopologyMVK;
/**
* Replacement for the sampleMask property.
*
* This property allows support under all OS versions. Delegates to the sampleMask
* property if it is available. otherwise, returns 0xFFFFFFFF when
* read and does nothing when set.
*/
@property(nonatomic, readwrite) NSUInteger sampleMaskMVK;
@end

View File

@ -20,6 +20,16 @@
#include "MTLRenderPipelineDescriptor+MoltenVK.h"
#include "MVKCommonEnvironment.h"
#if MVK_USE_METAL_PRIVATE_API
// These properties aren't public yet.
@interface MTLRenderPipelineDescriptor ()
@property(nonatomic, readwrite) NSUInteger sampleMask;
@property(nonatomic, readwrite) float sampleCoverage;
@end
#endif
@implementation MTLRenderPipelineDescriptor (MoltenVK)
-(MTLPrimitiveTopologyClass) inputPrimitiveTopologyMVK {
@ -31,4 +41,15 @@
if ([self respondsToSelector: @selector(setInputPrimitiveTopology:)]) { [self setInputPrimitiveTopology:topology]; }
}
#if MVK_USE_METAL_PRIVATE_API
-(NSUInteger) sampleMaskMVK {
if ( [self respondsToSelector: @selector(sampleMask)] ) { return self.sampleMask; }
return 0xFFFFFFFFFFFFFFFFULL;
}
-(void) setSampleMaskMVK: (NSUInteger) mask {
if ([self respondsToSelector: @selector(setSampleMask:)]) { self.sampleMask = mask; }
}
#endif
@end

View File

@ -41,4 +41,13 @@
*/
@property(nonatomic, readwrite) /*MTLSamplerBorderColor*/ NSUInteger borderColorMVK;
/**
* Replacement for the lodBias property.
*
* This property allows support under all OS versions. Delegates to the lodBias
* property if it is available. otherwise, returns 0 when read and
* does nothing when set.
*/
@property(nonatomic, readwrite) float lodBiasMVK;
@end

View File

@ -21,6 +21,15 @@
#include "MVKCommonEnvironment.h"
#if MVK_USE_METAL_PRIVATE_API
/** Additional methods not necessarily declared in <Metal/MTLSampler.h>. */
@interface MTLSamplerDescriptor ()
@property(nonatomic, readwrite) float lodBias;
@end
#endif
@implementation MTLSamplerDescriptor (MoltenVK)
-(MTLCompareFunction) compareFunctionMVK {
@ -45,4 +54,15 @@
#endif
}
#if MVK_USE_METAL_PRIVATE_API
-(float) lodBiasMVK {
if ( [self respondsToSelector: @selector(lodBias)] ) { return self.lodBias; }
return 0.0f;
}
-(void) setLodBiasMVK: (float) bias {
if ( [self respondsToSelector: @selector(setLodBias:)] ) { self.lodBias = bias; }
}
#endif
@end

View File

@ -81,6 +81,8 @@ MVK_CONFIG_MEMBER(useMetalArgumentBuffers, MVKUseMetalArgumentBuf
MVK_CONFIG_MEMBER(shaderSourceCompressionAlgorithm, MVKConfigCompressionAlgorithm, SHADER_COMPRESSION_ALGORITHM)
MVK_CONFIG_MEMBER(shouldMaximizeConcurrentCompilation, VkBool32, SHOULD_MAXIMIZE_CONCURRENT_COMPILATION)
MVK_CONFIG_MEMBER(timestampPeriodLowPassAlpha, float, TIMESTAMP_PERIOD_LOWPASS_ALPHA)
MVK_CONFIG_MEMBER(useMetalPrivateAPI, VkBool32, USE_METAL_PRIVATE_API)
MVK_CONFIG_MEMBER(_unused_struct_padding, uint32_t, _UNUSED_STRUCT_PADDING)
#undef MVK_CONFIG_MEMBER
#undef MVK_CONFIG_MEMBER_STRING

View File

@ -66,6 +66,9 @@ void mvkSetConfig(MVKConfiguration& dstMVKConfig, const MVKConfiguration& srcMVK
// Clamp timestampPeriodLowPassAlpha between 0.0 and 1.0.
dstMVKConfig.timestampPeriodLowPassAlpha = mvkClamp(dstMVKConfig.timestampPeriodLowPassAlpha, 0.0f, 1.0f);
// Only allow useMetalPrivateAPI to be enabled if we were built with support for it.
dstMVKConfig.useMetalPrivateAPI = dstMVKConfig.useMetalPrivateAPI && MVK_USE_METAL_PRIVATE_API;
// For each string member of the destination MVKConfiguration, store the contents
// in a std::string, then repoint the member to the contents of the std::string.
#define MVK_CONFIG_MEMBER(member, mbrType, name)

View File

@ -23,7 +23,9 @@
#include "mvk_vulkan.h"
#include "mvk_private_api.h"
#include "MVKLogging.h"
#ifdef __cplusplus
#include <string>
#endif
// Expose MoltenVK Apple surface extension functionality
@ -73,23 +75,12 @@
# define MVK_SUPPORT_IOSURFACE_BOOL (__TV_OS_VERSION_MIN_REQUIRED >= __TVOS_11_0)
#endif
/**
* Enable use of private Metal APIs.
*
* Enabling this build setting during a MoltenVK build will allow MoltenVK to
* extend its functionality by using certain private Metal API calls, but it
* will also disqualify the app from being distributed via Apple App Stores.
*
* Disabled by default.
*/
#ifndef MVK_USE_METAL_PRIVATE_API
# define MVK_USE_METAL_PRIVATE_API 0
#endif
#pragma mark -
#pragma mark MoltenVK Configuration
#ifdef __cplusplus
/** The number of members of MVKConfiguration that are strings. */
static constexpr uint32_t kMVKConfigurationStringCount = 1;
@ -105,6 +96,8 @@ void mvkSetGlobalConfig(const MVKConfiguration& srcMVKConfig);
*/
void mvkSetConfig(MVKConfiguration& dstMVKConfig, const MVKConfiguration& srcMVKConfig, std::string* stringHolders);
#endif
/**
* Enable debug mode.
* By default, disabled for Release builds and enabled for Debug builds.
@ -348,3 +341,14 @@ void mvkSetConfig(MVKConfiguration& dstMVKConfig, const MVKConfiguration& srcMVK
#ifndef MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA
# define MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA 1.0
#endif
/**
* Enable the use of Metal private interfaces, also known as "Service Provider Interfaces" (SPIs),
* to support Vulkan features. Enabled by default if support is included.
*/
#ifndef MVK_CONFIG_USE_METAL_PRIVATE_API
# define MVK_CONFIG_USE_METAL_PRIVATE_API MVK_USE_METAL_PRIVATE_API
#endif
#undef MVK_CONFIG__UNUSED_STRUCT_PADDING
#define MVK_CONFIG__UNUSED_STRUCT_PADDING 0

View File

@ -433,6 +433,52 @@ MVK_PUBLIC_SYMBOL MTLBlendFactor mvkMTLBlendFactorFromVkBlendFactor(VkBlendFacto
}
}
#if MVK_USE_METAL_PRIVATE_API
// This isn't in any public header yet. I'm really just guessing based on the D3D11 values here.
typedef NS_ENUM(NSUInteger, MTLLogicOperation) {
MTLLogicOperationClear,
MTLLogicOperationSet,
MTLLogicOperationCopy,
MTLLogicOperationCopyInverted,
MTLLogicOperationNoop,
MTLLogicOperationInvert,
MTLLogicOperationAnd,
MTLLogicOperationNand,
MTLLogicOperationOr,
MTLLogicOperationNor,
MTLLogicOperationXor,
MTLLogicOperationEquivalence,
MTLLogicOperationAndReverse,
MTLLogicOperationAndInverted,
MTLLogicOperationOrReverse,
MTLLogicOperationOrInverted,
};
MVK_PUBLIC_SYMBOL NSUInteger mvkMTLLogicOperationFromVkLogicOp(VkLogicOp vkLogicOp) {
switch (vkLogicOp) {
case VK_LOGIC_OP_CLEAR: return MTLLogicOperationClear;
case VK_LOGIC_OP_AND: return MTLLogicOperationAnd;
case VK_LOGIC_OP_AND_REVERSE: return MTLLogicOperationAndReverse;
case VK_LOGIC_OP_COPY: return MTLLogicOperationCopy;
case VK_LOGIC_OP_AND_INVERTED: return MTLLogicOperationAndInverted;
case VK_LOGIC_OP_NO_OP: return MTLLogicOperationNoop;
case VK_LOGIC_OP_XOR: return MTLLogicOperationXor;
case VK_LOGIC_OP_OR: return MTLLogicOperationOr;
case VK_LOGIC_OP_NOR: return MTLLogicOperationNor;
case VK_LOGIC_OP_EQUIVALENT: return MTLLogicOperationEquivalence;
case VK_LOGIC_OP_INVERT: return MTLLogicOperationInvert;
case VK_LOGIC_OP_OR_REVERSE: return MTLLogicOperationOrReverse;
case VK_LOGIC_OP_COPY_INVERTED: return MTLLogicOperationCopyInverted;
case VK_LOGIC_OP_OR_INVERTED: return MTLLogicOperationOrInverted;
case VK_LOGIC_OP_NAND: return MTLLogicOperationNand;
case VK_LOGIC_OP_SET: return MTLLogicOperationSet;
default: return MTLLogicOperationCopy;
}
}
#endif
MVK_PUBLIC_SYMBOL MTLVertexStepFunction mvkMTLVertexStepFunctionFromVkVertexInputRate(VkVertexInputRate vkVtxStep) {
switch (vkVtxStep) {
case VK_VERTEX_INPUT_RATE_VERTEX: return MTLVertexStepFunctionPerVertex;

View File

@ -1498,6 +1498,7 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthBounds(
float maxDepthBounds) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetDepthBounds, commandBuffer, minDepthBounds, maxDepthBounds);
MVKTraceVulkanCallEnd();
}
@ -2653,6 +2654,7 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthBoundsTestEnable(
VkBool32 depthBoundsTestEnable) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetDepthBoundsTestEnable, commandBuffer, depthBoundsTestEnable);
MVKTraceVulkanCallEnd();
}

View File

@ -317,9 +317,10 @@ _Vulkan_ API calls as function pointers.
<a name="metal_private_api"></a>
### Accessing _Metal_ Private API calls
You can optionally build **MoltenVK** with access to private _Metal_ API calls.
Doing so will allow **MoltenVK** to extend its functionality by using certain private _Metal_
API calls, but it will also disqualify the app from being distributed via _Apple_ App Stores.
You can optionally build **MoltenVK** with access to private _Metal_ API calls, also known
as "Service Provider Interfaces" (SPIs). Doing so will allow **MoltenVK** to extend its
functionality by using certain private _Metal_ API calls, but it will also disqualify the
app from being distributed via _Apple_ App Stores.
To do so, when building **MoltenVK**, set the build setting `MVK_USE_METAL_PRIVATE_API=1`.
This build setting can be set in the `MoltenVK.xcodeproj` *Xcode* project, or it can be
@ -327,6 +328,10 @@ included in any of the `make` command-line build commands [mentioned above](#com
Functionality added with `MVK_USE_METAL_PRIVATE_API` enabled includes:
- `VkPhysicalDeviceFeatures::wideLines`
- `VkPhysicalDeviceFeatures::logicOp`
- `VkPhysicalDeviceFeatures::depthBounds` *(requires an AMD GPU)*
- `VkPhysicalDevicePortabilitySubsetFeaturesKHR::samplerMipLodBias`
- `VkGraphicsPipelineRasterizationCreateInfo::sampleMask`, using `MTLRenderPipelineDescriptor.sampleMask` instead of emulating it in the fragment shader
<a name="demos"></a>