From cd5b336bec435a4538250d27ef5415001215db93 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Fri, 29 Apr 2022 22:14:05 -0400 Subject: [PATCH] Add support for VK_EXT_separate_stencil_usage extension. --- Docs/Whats_New.md | 3 +- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 10 +++++- MoltenVK/MoltenVK/GPUObjects/MVKImage.h | 2 ++ MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 37 ++++++++++++++++------ MoltenVK/MoltenVK/Layers/MVKExtensions.def | 1 + 5 files changed, 41 insertions(+), 12 deletions(-) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 1cc7404b..2718328d 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -19,10 +19,11 @@ MoltenVK 1.1.10 Released TBD - Add support for extensions: - - `VK_KHR_dynamic_rendering` - `VK_KHR_portability_enumeration` support added to `MoltenVK_icd.json`, and documentation updated to indicate the impact of the `VK_KHR_portability_enumeration` extension during runtime loading on *macOS* via the *Vulkan Loader*. + - `VK_KHR_dynamic_rendering` + - `VK_EXT_separate_stencil_usage` - Fix error where previously bound push constants can override a descriptor buffer binding used by a subsequent pipeline that does not use push constants. - Support attachment clearing when some clearing formats are not specified. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 6ad5cd4a..520a4644 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -736,6 +736,7 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) { + auto usage = pImageFormatInfo->usage; for (const auto* nextInfo = (VkBaseInStructure*)pImageFormatInfo->pNext; nextInfo; nextInfo = nextInfo->pNext) { switch (nextInfo->sType) { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: { @@ -750,6 +751,13 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImage } break; } + case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO: { + // If the format includes a stencil component, combine any separate stencil usage with non-stencil usage. + if (_pixelFormats.isStencilFormat(_pixelFormats.getMTLPixelFormat(pImageFormatInfo->format))) { + usage |= ((VkImageStencilUsageCreateInfo*)nextInfo)->stencilUsage; + } + break; + } default: break; } @@ -770,7 +778,7 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImage if ( !_pixelFormats.isSupported(pImageFormatInfo->format) ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } return getImageFormatProperties(pImageFormatInfo->format, pImageFormatInfo->type, - pImageFormatInfo->tiling, pImageFormatInfo->usage, + pImageFormatInfo->tiling, usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties); } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h index e7607e60..b56eeb0d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -344,6 +344,7 @@ protected: void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes); void releaseIOSurface(); bool getIsValidViewFormat(VkFormat viewFormat); + VkImageUsageFlags getCombinedUsage() { return _usage | _stencilUsage; } MTLTextureUsage getMTLTextureUsage(MTLPixelFormat mtlPixFmt); MVKSmallVector _memoryBindings; @@ -354,6 +355,7 @@ protected: uint32_t _arrayLayers; VkSampleCountFlagBits _samples; VkImageUsageFlags _usage; + VkImageUsageFlags _stencilUsage; VkFormat _vkFormat; MTLTextureType _mtlTextureType; std::mutex _lock; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 9853d766..379ed9d2 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -392,7 +392,7 @@ VkResult MVKImageMemoryBinding::getMemoryRequirements(const void*, VkMemoryRequi switch (next->sType) { case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { auto* dedicatedReqs = (VkMemoryDedicatedRequirements*)next; - bool writable = mvkIsAnyFlagEnabled(_image->_usage, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + bool writable = mvkIsAnyFlagEnabled(_image->getCombinedUsage(), VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); bool canUseTexelBuffer = _device->_pMetalFeatures->texelBuffers && _image->_isLinear && !_image->getIsCompressed(); dedicatedReqs->requiresDedicatedAllocation = _requiresDedicatedMemoryAllocation; dedicatedReqs->prefersDedicatedAllocation = (dedicatedReqs->requiresDedicatedAllocation || @@ -609,7 +609,7 @@ void MVKImage::getTransferDescriptorData(MVKImageDescriptorData& imgData) { imgData.mipLevels = _mipLevels; imgData.arrayLayers = _arrayLayers; imgData.samples = _samples; - imgData.usage = _usage; + imgData.usage = getCombinedUsage(); } // Returns whether an MVKImageView can have the specified format. @@ -651,8 +651,8 @@ VkResult MVKImage::getMemoryRequirements(VkMemoryRequirements* pMemoryRequiremen // Only transient attachments may use memoryless storage. // Using memoryless as an input attachment requires shader framebuffer fetch, which MoltenVK does not support yet. // TODO: support framebuffer fetch so VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT uses color(m) in shader instead of setFragmentTexture:, which crashes Metal - if (!mvkIsAnyFlagEnabled(_usage, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) || - mvkIsAnyFlagEnabled(_usage, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) ) { + if (!mvkIsAnyFlagEnabled(getCombinedUsage(), VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) || + mvkIsAnyFlagEnabled(getCombinedUsage(), VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) ) { mvkDisableFlags(pMemoryRequirements->memoryTypeBits, getPhysicalDevice()->getLazilyAllocatedMemoryTypes()); } @@ -725,6 +725,7 @@ VkResult MVKImage::setMTLTexture(uint8_t planeIndex, id mtlTexture) _samples = mvkVkSampleCountFlagBitsFromSampleCount(mtlTexture.sampleCount); _arrayLayers = uint32_t(mtlTexture.arrayLength); _usage = getPixelFormats()->getVkImageUsageFlags(mtlTexture.usage, mtlTexture.pixelFormat); + _stencilUsage = _usage; if (_device->_pMetalFeatures->ioSurfaces) { _ioSurface = mtlTexture.iosurface; @@ -848,7 +849,7 @@ MTLTextureUsage MVKImage::getMTLTextureUsage(MTLPixelFormat mtlPixFmt) { needsReinterpretation = needsReinterpretation || !pixFmts->compatibleAsLinearOrSRGB(mtlPixFmt, viewFmt); } - MTLTextureUsage mtlUsage = pixFmts->getMTLTextureUsage(_usage, mtlPixFmt, _samples, _isLinear, needsReinterpretation, _hasExtendedUsage); + MTLTextureUsage mtlUsage = pixFmts->getMTLTextureUsage(getCombinedUsage(), mtlPixFmt, _samples, _isLinear, needsReinterpretation, _hasExtendedUsage); // Metal before 3.0 doesn't support 3D compressed textures, so we'll // decompress the texture ourselves, and we need to be able to write to it. @@ -865,6 +866,10 @@ MTLTextureUsage MVKImage::getMTLTextureUsage(MTLPixelFormat mtlPixFmt) { MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) { _ioSurface = nil; + // Stencil usage is implied to be the same as usage, unless overridden in the pNext chain. + _usage = pCreateInfo->usage; + _stencilUsage = _usage; + const VkExternalMemoryImageCreateInfo* pExtMemInfo = nullptr; for (const auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { switch (next->sType) { @@ -880,6 +885,9 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV } break; } + case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO: + _stencilUsage = ((VkImageStencilUsageCreateInfo*)next)->stencilUsage; + break; default: break; } @@ -908,7 +916,6 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV MVKPixelFormats* pixFmts = getPixelFormats(); _vkFormat = pCreateInfo->format; - _usage = pCreateInfo->usage; _isAliasable = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_ALIAS_BIT); _hasMutableFormat = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT); _hasExtendedUsage = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_EXTENDED_USAGE_BIT); @@ -916,7 +923,7 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV // If this is a storage image of format R32_UINT or R32_SINT, or MUTABLE_FORMAT is set // and R32_UINT is in the set of possible view formats, then we must use a texel buffer, // or image atomics won't work. - _isLinearForAtomics = (_isLinear && mvkIsAnyFlagEnabled(_usage, VK_IMAGE_USAGE_STORAGE_BIT) && + _isLinearForAtomics = (_isLinear && mvkIsAnyFlagEnabled(getCombinedUsage(), VK_IMAGE_USAGE_STORAGE_BIT) && ((_vkFormat == VK_FORMAT_R32_UINT || _vkFormat == VK_FORMAT_R32_SINT) || (_hasMutableFormat && pixFmts->getViewClass(_vkFormat) == MVKMTLViewClass::Color32 && (getIsValidViewFormat(VK_FORMAT_R32_UINT) || getIsValidViewFormat(VK_FORMAT_R32_SINT))))); @@ -1751,12 +1758,22 @@ void MVKImageView::populateMTLRenderPassAttachmentDescriptorResolve(MTLRenderPas MVKImageView::MVKImageView(MVKDevice* device, const VkImageViewCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) { _image = (MVKImage*)pCreateInfo->image; - // Transfer commands don't use image views. - _usage = _image->_usage; - mvkDisableFlags(_usage, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)); _mtlTextureType = mvkMTLTextureTypeFromVkImageViewType(pCreateInfo->viewType, _image->getSampleCount() != VK_SAMPLE_COUNT_1_BIT); + // Per spec, for depth/stencil formats, determine the appropriate usage + // based on whether stencil or depth or both aspects are being used. + VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask; + if (mvkAreAllFlagsEnabled(aspectMask, VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)) { + _usage = _image->_usage & _image->_stencilUsage; + } else if (mvkIsAnyFlagEnabled(aspectMask, VK_IMAGE_ASPECT_STENCIL_BIT)) { + _usage = _image->_stencilUsage; + } else { + _usage = _image->_usage; + } + // Image views can't be used in transfer commands. + mvkDisableFlags(_usage, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)); + for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { switch (next->sType) { case VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO: { diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index a305685b..b0ae8306 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -98,6 +98,7 @@ MVK_EXTENSION(EXT_private_data, EXT_PRIVATE_DATA, MVK_EXTENSION(EXT_robustness2, EXT_ROBUSTNESS_2, DEVICE, 10.11, 8.0) MVK_EXTENSION(EXT_sample_locations, EXT_SAMPLE_LOCATIONS, DEVICE, 10.13, 11.0) MVK_EXTENSION(EXT_scalar_block_layout, EXT_SCALAR_BLOCK_LAYOUT, DEVICE, 10.11, 8.0) +MVK_EXTENSION(EXT_separate_stencil_usage, EXT_SEPARATE_STENCIL_USAGE, DEVICE, 10.11, 8.0) MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT, DEVICE, 10.14, 12.0) MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER, DEVICE, 10.11, 8.0) MVK_EXTENSION(EXT_subgroup_size_control, EXT_SUBGROUP_SIZE_CONTROL, DEVICE, 10.14, 13.0)