Advertise the VK_EXT_shader_stencil_export extension.
This is supported by Mac GPU Family 2 starting on macOS 10.14, and Apple GPU Family 5 starting on iOS 12. Supporting this is a bit tricky. Because only some devices support this extension, we now have to keep track of supported device extensions per device.
This commit is contained in:
parent
53b6ced8b3
commit
fc13aec2af
@ -240,7 +240,7 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following
|
|||||||
- `VK_KHR_maintenance3`
|
- `VK_KHR_maintenance3`
|
||||||
- `VK_KHR_push_descriptor`
|
- `VK_KHR_push_descriptor`
|
||||||
- `VK_KHR_relaxed_block_layout`
|
- `VK_KHR_relaxed_block_layout`
|
||||||
- `VK_KHR_sampler_mirror_clamp_to_edge`
|
- `VK_KHR_sampler_mirror_clamp_to_edge` *(macOS)*
|
||||||
- `VK_KHR_shader_draw_parameters`
|
- `VK_KHR_shader_draw_parameters`
|
||||||
- `VK_KHR_shader_float16_int8`
|
- `VK_KHR_shader_float16_int8`
|
||||||
- `VK_KHR_storage_buffer_storage_class`
|
- `VK_KHR_storage_buffer_storage_class`
|
||||||
@ -254,6 +254,7 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following
|
|||||||
- `VK_EXT_host_query_reset`
|
- `VK_EXT_host_query_reset`
|
||||||
- `VK_EXT_memory_budget`
|
- `VK_EXT_memory_budget`
|
||||||
- `VK_EXT_metal_surface`
|
- `VK_EXT_metal_surface`
|
||||||
|
- `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)*
|
||||||
- `VK_EXT_shader_viewport_index_layer`
|
- `VK_EXT_shader_viewport_index_layer`
|
||||||
- `VK_EXT_vertex_attribute_divisor`
|
- `VK_EXT_vertex_attribute_divisor`
|
||||||
- `VK_EXTX_portability_subset`
|
- `VK_EXTX_portability_subset`
|
||||||
|
@ -537,6 +537,7 @@ typedef struct {
|
|||||||
VkBool32 events; /**< If true, Metal synchronization events are supported. */
|
VkBool32 events; /**< If true, Metal synchronization events are supported. */
|
||||||
VkBool32 memoryBarriers; /**< If true, full memory barriers within Metal render passes are supported. */
|
VkBool32 memoryBarriers; /**< If true, full memory barriers within Metal render passes are supported. */
|
||||||
VkBool32 multisampleLayeredRendering; /**< If true, layered rendering to multiple multi-sampled cube or texture array layers is supported. */
|
VkBool32 multisampleLayeredRendering; /**< If true, layered rendering to multiple multi-sampled cube or texture array layers is supported. */
|
||||||
|
VkBool32 stencilFeedback; /**< If true, fragment shaders that write to [[stencil]] outputs are supported. */
|
||||||
} MVKPhysicalDeviceMetalFeatures;
|
} MVKPhysicalDeviceMetalFeatures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,6 +88,9 @@ public:
|
|||||||
/** Returns a pointer to the Vulkan instance. */
|
/** Returns a pointer to the Vulkan instance. */
|
||||||
MVKInstance* getInstance() override { return _mvkInstance; }
|
MVKInstance* getInstance() override { return _mvkInstance; }
|
||||||
|
|
||||||
|
/** Populates the specified array with the supported extensions of this device. */
|
||||||
|
VkResult getExtensionProperties(const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties);
|
||||||
|
|
||||||
/** Populates the specified structure with the features of this device. */
|
/** Populates the specified structure with the features of this device. */
|
||||||
void getFeatures(VkPhysicalDeviceFeatures* features);
|
void getFeatures(VkPhysicalDeviceFeatures* features);
|
||||||
|
|
||||||
@ -318,6 +321,8 @@ protected:
|
|||||||
void initFeatures();
|
void initFeatures();
|
||||||
void initProperties();
|
void initProperties();
|
||||||
void initMemoryProperties();
|
void initMemoryProperties();
|
||||||
|
void initExtensions();
|
||||||
|
MVKExtensionList* getSupportedExtensions(const char* pLayerName = nullptr);
|
||||||
std::vector<MVKQueueFamily*>& getQueueFamilies();
|
std::vector<MVKQueueFamily*>& getQueueFamilies();
|
||||||
void initPipelineCacheUUID();
|
void initPipelineCacheUUID();
|
||||||
MTLFeatureSet getHighestMTLFeatureSet();
|
MTLFeatureSet getHighestMTLFeatureSet();
|
||||||
@ -327,6 +332,7 @@ protected:
|
|||||||
|
|
||||||
id<MTLDevice> _mtlDevice;
|
id<MTLDevice> _mtlDevice;
|
||||||
MVKInstance* _mvkInstance;
|
MVKInstance* _mvkInstance;
|
||||||
|
MVKExtensionList _supportedExtensions;
|
||||||
VkPhysicalDeviceFeatures _features;
|
VkPhysicalDeviceFeatures _features;
|
||||||
MVKPhysicalDeviceMetalFeatures _metalFeatures;
|
MVKPhysicalDeviceMetalFeatures _metalFeatures;
|
||||||
VkPhysicalDeviceProperties _properties;
|
VkPhysicalDeviceProperties _properties;
|
||||||
|
@ -56,6 +56,11 @@ using namespace std;
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKPhysicalDevice
|
#pragma mark MVKPhysicalDevice
|
||||||
|
|
||||||
|
VkResult MVKPhysicalDevice::getExtensionProperties(const char* pLayerName, uint32_t* pCount, VkExtensionProperties* pProperties) {
|
||||||
|
MVKExtensionList* extensions = getSupportedExtensions(pLayerName);
|
||||||
|
return extensions->getProperties(pCount, pProperties);
|
||||||
|
}
|
||||||
|
|
||||||
void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures* features) {
|
void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures* features) {
|
||||||
if (features) { *features = _features; }
|
if (features) { *features = _features; }
|
||||||
}
|
}
|
||||||
@ -676,7 +681,7 @@ VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMe
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtlDevice) {
|
MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtlDevice) : _supportedExtensions(this, true) {
|
||||||
_mvkInstance = mvkInstance;
|
_mvkInstance = mvkInstance;
|
||||||
_mtlDevice = [mtlDevice retain];
|
_mtlDevice = [mtlDevice retain];
|
||||||
|
|
||||||
@ -684,6 +689,7 @@ MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtl
|
|||||||
initFeatures(); // Call second.
|
initFeatures(); // Call second.
|
||||||
initProperties(); // Call third.
|
initProperties(); // Call third.
|
||||||
initMemoryProperties();
|
initMemoryProperties();
|
||||||
|
initExtensions();
|
||||||
logGPUInfo();
|
logGPUInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,6 +757,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
|
|||||||
|
|
||||||
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily5_v1] ) {
|
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily5_v1] ) {
|
||||||
_metalFeatures.layeredRendering = true;
|
_metalFeatures.layeredRendering = true;
|
||||||
|
_metalFeatures.stencilFeedback = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -793,6 +800,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
|
|||||||
|
|
||||||
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily2_v1] ) {
|
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily2_v1] ) {
|
||||||
_metalFeatures.multisampleLayeredRendering = _metalFeatures.layeredRendering;
|
_metalFeatures.multisampleLayeredRendering = _metalFeatures.layeredRendering;
|
||||||
|
_metalFeatures.stencilFeedback = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1499,6 +1507,18 @@ void MVKPhysicalDevice::initMemoryProperties() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MVKPhysicalDevice::initExtensions() {
|
||||||
|
if (!_metalFeatures.stencilFeedback) {
|
||||||
|
_supportedExtensions.vk_EXT_shader_stencil_export.enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return all extensions supported by this physical device.
|
||||||
|
MVKExtensionList* MVKPhysicalDevice::getSupportedExtensions(const char* pLayerName) {
|
||||||
|
if (!pLayerName || strcmp(pLayerName, "MoltenVK") == 0) { return &_supportedExtensions; }
|
||||||
|
return getInstance()->getLayerManager()->getLayerNamed(pLayerName)->getSupportedExtensions();
|
||||||
|
}
|
||||||
|
|
||||||
void MVKPhysicalDevice::logGPUInfo() {
|
void MVKPhysicalDevice::logGPUInfo() {
|
||||||
string devTypeStr;
|
string devTypeStr;
|
||||||
switch (_properties.deviceType) {
|
switch (_properties.deviceType) {
|
||||||
@ -2280,7 +2300,7 @@ void MVKDevice::enableExtensions(const VkDeviceCreateInfo* pCreateInfo) {
|
|||||||
MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_enabledExtensions;
|
MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_enabledExtensions;
|
||||||
setConfigurationResult(pWritableExtns->enable(pCreateInfo->enabledExtensionCount,
|
setConfigurationResult(pWritableExtns->enable(pCreateInfo->enabledExtensionCount,
|
||||||
pCreateInfo->ppEnabledExtensionNames,
|
pCreateInfo->ppEnabledExtensionNames,
|
||||||
getInstance()->getDriverLayer()->getSupportedExtensions()));
|
getPhysicalDevice()->getSupportedExtensions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the command queues
|
// Create the command queues
|
||||||
|
@ -58,6 +58,7 @@ MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS)
|
|||||||
MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET)
|
MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET)
|
||||||
MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET)
|
MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET)
|
||||||
MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE)
|
MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE)
|
||||||
|
MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT)
|
||||||
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
|
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
|
||||||
MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR)
|
MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR)
|
||||||
MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET)
|
MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET)
|
||||||
|
@ -85,6 +85,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string enabledNamesString(const char* separator = " ", bool prefixFirstWithSeparator = false) const;
|
std::string enabledNamesString(const char* separator = " ", bool prefixFirstWithSeparator = false) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If pProperties is null, the value of pCount is updated with the number of extensions
|
||||||
|
* enabled in this list.
|
||||||
|
*
|
||||||
|
* If pProperties is not null, then pCount extension properties are copied into the array.
|
||||||
|
* If the number of available extensions is less than pCount, the value of pCount is updated
|
||||||
|
* to indicate the number of extension properties actually returned in the array.
|
||||||
|
*
|
||||||
|
* Returns VK_SUCCESS if successful. Returns VK_INCOMPLETE if the number of extensions
|
||||||
|
* enabled in this list is larger than the specified pCount. Returns other values
|
||||||
|
* if an error occurs.
|
||||||
|
*/
|
||||||
|
VkResult getProperties(uint32_t* pCount, VkExtensionProperties* pProperties);
|
||||||
|
|
||||||
MVKExtensionList(MVKVulkanAPIObject* apiObject, bool enableForPlatform = false);
|
MVKExtensionList(MVKVulkanAPIObject* apiObject, bool enableForPlatform = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -50,6 +50,9 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
|
|||||||
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
|
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
|
||||||
return mvkOSVersion() >= 10.13;
|
return mvkOSVersion() >= 10.13;
|
||||||
}
|
}
|
||||||
|
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
|
||||||
|
return mvkOSVersion() >= 10.14;
|
||||||
|
}
|
||||||
if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
|
if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
|
||||||
if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
|
if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
|
||||||
#endif
|
#endif
|
||||||
@ -58,6 +61,9 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
|
|||||||
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
|
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
|
||||||
return mvkOSVersion() >= 11.0;
|
return mvkOSVersion() >= 11.0;
|
||||||
}
|
}
|
||||||
|
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
|
||||||
|
return mvkOSVersion() >= 12.0;
|
||||||
|
}
|
||||||
if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
|
if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -157,3 +163,31 @@ string MVKExtensionList::enabledNamesString(const char* separator, bool prefixFi
|
|||||||
}
|
}
|
||||||
return logMsg;
|
return logMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkResult MVKExtensionList::getProperties(uint32_t* pCount, VkExtensionProperties* pProperties) {
|
||||||
|
|
||||||
|
uint32_t enabledCnt = 0;
|
||||||
|
|
||||||
|
// Iterate extensions and handle those that are enabled. Count them,
|
||||||
|
// and if they are to be returned, and there is room, do so.
|
||||||
|
uint32_t extnCnt = getCount();
|
||||||
|
MVKExtension* extnAry = &extensionArray;
|
||||||
|
for (uint32_t extnIdx = 0; extnIdx < extnCnt; extnIdx++) {
|
||||||
|
if (extnAry[extnIdx].enabled) {
|
||||||
|
if (pProperties) {
|
||||||
|
if (enabledCnt < *pCount) {
|
||||||
|
pProperties[enabledCnt] = *(extnAry[extnIdx].pProperties);
|
||||||
|
} else {
|
||||||
|
return VK_INCOMPLETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enabledCnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the count of enabled extensions. This will either be a
|
||||||
|
// count of all enabled extensions, or a count of those returned.
|
||||||
|
*pCount = enabledCnt;
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -32,29 +32,7 @@ VkLayerProperties* const MVKLayer::getLayerProperties() { return &_layerProperti
|
|||||||
|
|
||||||
VkResult MVKLayer::getExtensionProperties(uint32_t* pCount, VkExtensionProperties* pProperties) {
|
VkResult MVKLayer::getExtensionProperties(uint32_t* pCount, VkExtensionProperties* pProperties) {
|
||||||
|
|
||||||
uint32_t enabledCnt = 0;
|
return _supportedExtensions.getProperties(pCount, pProperties);
|
||||||
|
|
||||||
// Iterate extensions and handle those that are enabled. Count them,
|
|
||||||
// and if they are to be returned, and there is room, do so.
|
|
||||||
uint32_t extnCnt = _supportedExtensions.getCount();
|
|
||||||
MVKExtension* extnAry = &_supportedExtensions.extensionArray;
|
|
||||||
for (uint32_t extnIdx = 0; extnIdx < extnCnt; extnIdx++) {
|
|
||||||
if (extnAry[extnIdx].enabled) {
|
|
||||||
if (pProperties) {
|
|
||||||
if (enabledCnt < *pCount) {
|
|
||||||
pProperties[enabledCnt] = *(extnAry[extnIdx].pProperties);
|
|
||||||
} else {
|
|
||||||
return VK_INCOMPLETE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enabledCnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the count of enabled extensions. This will either be a
|
|
||||||
// count of all enabled extensions, or a count of those returned.
|
|
||||||
*pCount = enabledCnt;
|
|
||||||
return VK_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ MVK_PUBLIC_SYMBOL VkResult vkEnumerateDeviceExtensionProperties(
|
|||||||
|
|
||||||
MVKTraceVulkanCallStart();
|
MVKTraceVulkanCallStart();
|
||||||
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
|
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
|
||||||
VkResult rslt = mvkPD->getInstance()->getLayerManager()->getLayerNamed(pLayerName)->getExtensionProperties(pCount, pProperties);
|
VkResult rslt = mvkPD->getExtensionProperties(pLayerName, pCount, pProperties);
|
||||||
MVKTraceVulkanCallEnd();
|
MVKTraceVulkanCallEnd();
|
||||||
return rslt;
|
return rslt;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user