From e4dbb8044ad34573ed55a47e9550236c81fd9162 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Tue, 1 Sep 2020 20:43:22 -0500 Subject: [PATCH] Support linear images and buffer views in shared memory on macOS 10.15.5+. Apple assured me that, starting in 10.15.5, linear textures and texture buffers can be created from buffers with `Shared` storage. I have tested this and can confirm that it works at least on Big Sur, and probably on Catalina as well. --- MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 1 + MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm | 4 ++-- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 5 +++++ MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm | 6 ++++-- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 17 +++++++---------- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index 309097ac..3b67b4d5 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -617,6 +617,7 @@ typedef struct { VkBool32 nonUniformThreadgroups; /**< If true, the device supports arbitrary-sized grids in compute workloads. */ VkBool32 renderWithoutAttachments; /**< If true, we don't have to create a dummy attachment for a render pass if there isn't one. */ VkBool32 deferredStoreActions; /**< If true, render pass store actions can be specified after the render encoder is created. */ + VkBool32 sharedLinearTextures; /**< If true, linear textures and texture buffers can be created from buffers in Shared storage. */ } MVKPhysicalDeviceMetalFeatures; /** MoltenVK performance of a particular type of activity. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm index 92d39f25..de172729 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm @@ -84,7 +84,7 @@ VkResult MVKBuffer::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOf #if MVK_MACOS if (_deviceMemory) { - _isHostCoherentTexelBuffer = _deviceMemory->isMemoryHostCoherent() && mvkIsAnyFlagEnabled(_usage, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT); + _isHostCoherentTexelBuffer = !_device->_pMetalFeatures->sharedLinearTextures && _deviceMemory->isMemoryHostCoherent() && mvkIsAnyFlagEnabled(_usage, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT); } #endif @@ -272,7 +272,7 @@ id MVKBufferView::getMTLTexture() { } id mtlBuff; VkDeviceSize mtlBuffOffset; - if (MVK_MACOS && _buffer->isMemoryHostCoherent()) { + if ( !_device->_pMetalFeatures->sharedLinearTextures && _buffer->isMemoryHostCoherent() ) { mtlBuff = _buffer->getMTLBufferCache(); mtlBuffOffset = _offset; } else { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 83add582..6107b61f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -1026,6 +1026,7 @@ void MVKPhysicalDevice::initMetalFeatures() { _metalFeatures.texelBuffers = true; _metalFeatures.maxTextureDimension = (8 * KIBI); _metalFeatures.dynamicMTLBufferSize = (4 * KIBI); + _metalFeatures.sharedLinearTextures = true; if (supportsMTLFeatureSet(tvOS_GPUFamily1_v2)) { _metalFeatures.mslVersionEnum = MTLLanguageVersion1_2; @@ -1073,6 +1074,7 @@ void MVKPhysicalDevice::initMetalFeatures() { _metalFeatures.mtlCopyBufferAlignment = 1; _metalFeatures.texelBuffers = true; _metalFeatures.maxTextureDimension = (4 * KIBI); + _metalFeatures.sharedLinearTextures = true; if (supportsMTLFeatureSet(iOS_GPUFamily1_v2)) { _metalFeatures.mslVersionEnum = MTLLanguageVersion1_1; @@ -1186,6 +1188,9 @@ void MVKPhysicalDevice::initMetalFeatures() { _metalFeatures.mslVersionEnum = MTLLanguageVersion2_2; _metalFeatures.native3DCompressedTextures = true; _metalFeatures.renderWithoutAttachments = true; + if ( mvkOSVersionIsAtLeast(mvkMakeOSVersion(10, 15, 5)) ) { + _metalFeatures.sharedLinearTextures = true; + } if (supportsMTLGPUFamily(Mac2)) { _metalFeatures.nativeTextureSwizzle = true; _metalFeatures.placementHeaps = useMTLHeaps; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm index cfa410ed..593be4d1 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm @@ -308,8 +308,10 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device, if (!((MVKImage*)dedicatedImage)->_isLinear) { setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Host-coherent VkDeviceMemory objects cannot be associated with optimal-tiling images.")); } else { - // Need to use the managed mode for images. - _mtlStorageMode = MTLStorageModeManaged; + if (!_device->_pMetalFeatures->sharedLinearTextures) { + // Need to use the managed mode for images. + _mtlStorageMode = MTLStorageModeManaged; + } // Nonetheless, we need a buffer to be able to map the memory at will. if (!ensureMTLBuffer() ) { setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate a host-coherent VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a host-coherent VkDeviceMemory is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize)); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 951e6f77..505858e4 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -395,10 +395,8 @@ VkResult MVKImageMemoryBinding::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDevi _usesTexelBuffer = _device->_pMetalFeatures->texelBuffers && _deviceMemory && _deviceMemory->_mtlBuffer; // Texel buffers available _usesTexelBuffer = _usesTexelBuffer && (isMemoryHostAccessible() || _device->_pMetalFeatures->placementHeaps) && _image->_isLinear && !_image->getIsCompressed(); // Applicable memory layout -#if MVK_MACOS - // macOS cannot use shared memory for texel buffers. - _usesTexelBuffer = _usesTexelBuffer && !isMemoryHostCoherent(); -#endif + // macOS before 10.15.5 cannot use shared memory for texel buffers. + _usesTexelBuffer = _usesTexelBuffer && (_device->_pMetalFeatures->sharedLinearTextures || !isMemoryHostCoherent()); flushToDevice(getDeviceMemoryOffset(), getByteCount()); return _deviceMemory ? _deviceMemory->addImageMemoryBinding(this) : VK_SUCCESS; @@ -430,10 +428,9 @@ bool MVKImageMemoryBinding::needsHostReadSync(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, MVKPipelineBarrier& barrier) { #if MVK_MACOS - // On macOS, texture memory is never host-coherent, so don't test for it. return ((barrier.newLayout == VK_IMAGE_LAYOUT_GENERAL) && mvkIsAnyFlagEnabled(barrier.dstAccessMask, (VK_ACCESS_HOST_READ_BIT | VK_ACCESS_MEMORY_READ_BIT)) && - isMemoryHostAccessible()); + isMemoryHostAccessible() && (!_device->_pMetalFeatures->sharedLinearTextures || !isMemoryHostCoherent())); #endif #if MVK_IOS_OR_TVOS return false; @@ -761,10 +758,10 @@ MTLStorageMode MVKImage::getMTLStorageMode() { if (_ioSurface && stgMode == MTLStorageModePrivate) { stgMode = MTLStorageModeShared; } -#if MVK_MACOS - // For macOS, textures cannot use Shared storage mode, so change to Managed storage mode. - if (stgMode == MTLStorageModeShared) { stgMode = MTLStorageModeManaged; } -#endif + // For macOS prior to 10.15.5, textures cannot use Shared storage mode, so change to Managed storage mode. + if (stgMode == MTLStorageModeShared && !_device->_pMetalFeatures->sharedLinearTextures) { + stgMode = MTLStorageModeManaged; + } return stgMode; }