Add support for VK_KHR_external_memory extension.
Functions and functionality supported, but don't currently do anything until Metal-friendly enumerations added to VkExternalMemoryHandleTypeFlagBits. Updated What's New document.
This commit is contained in:
parent
2b3cf6f395
commit
d343fed52e
@ -20,7 +20,10 @@ MoltenVK 1.0.42
|
|||||||
Released TBD
|
Released TBD
|
||||||
|
|
||||||
- Add support for extensions:
|
- Add support for extensions:
|
||||||
- `VK_KHR_external_memory_capabilities`
|
- `VK_KHR_external_memory` (non-functional groundwork for future
|
||||||
|
Metal-resource Vulkan extension).
|
||||||
|
- `VK_KHR_external_memory_capabilities` (non-functional groundwork
|
||||||
|
for future Metal-resource Vulkan extension).
|
||||||
- Memory consumption improvements when handling Vulkan commands.
|
- Memory consumption improvements when handling Vulkan commands.
|
||||||
- Reinstate `VulkanSamples API-Samples` demo apps and add
|
- Reinstate `VulkanSamples API-Samples` demo apps and add
|
||||||
`input_attachment` and `push_descriptors` demos.
|
`input_attachment` and `push_descriptors` demos.
|
||||||
|
@ -92,6 +92,7 @@ protected:
|
|||||||
bool shouldFlushHostMemory();
|
bool shouldFlushHostMemory();
|
||||||
VkResult flushToDevice(VkDeviceSize offset, VkDeviceSize size);
|
VkResult flushToDevice(VkDeviceSize offset, VkDeviceSize size);
|
||||||
VkResult pullFromDevice(VkDeviceSize offset, VkDeviceSize size);
|
VkResult pullFromDevice(VkDeviceSize offset, VkDeviceSize size);
|
||||||
|
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
||||||
|
|
||||||
VkBufferUsageFlags _usage;
|
VkBufferUsageFlags _usage;
|
||||||
bool _isHostCoherentTexelBuffer = false;
|
bool _isHostCoherentTexelBuffer = false;
|
||||||
|
@ -66,8 +66,8 @@ VkResult MVKBuffer::getMemoryRequirements(const void*, VkMemoryRequirements2* pM
|
|||||||
switch (next->sType) {
|
switch (next->sType) {
|
||||||
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
|
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
|
||||||
auto* dedicatedReqs = (VkMemoryDedicatedRequirements*)next;
|
auto* dedicatedReqs = (VkMemoryDedicatedRequirements*)next;
|
||||||
dedicatedReqs->prefersDedicatedAllocation = VK_FALSE;
|
dedicatedReqs->requiresDedicatedAllocation = _requiresDedicatedMemoryAllocation;
|
||||||
dedicatedReqs->requiresDedicatedAllocation = VK_FALSE;
|
dedicatedReqs->prefersDedicatedAllocation = dedicatedReqs->requiresDedicatedAllocation;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -192,6 +192,28 @@ id<MTLBuffer> MVKBuffer::getMTLBuffer() {
|
|||||||
MVKBuffer::MVKBuffer(MVKDevice* device, const VkBufferCreateInfo* pCreateInfo) : MVKResource(device), _usage(pCreateInfo->usage) {
|
MVKBuffer::MVKBuffer(MVKDevice* device, const VkBufferCreateInfo* pCreateInfo) : MVKResource(device), _usage(pCreateInfo->usage) {
|
||||||
_byteAlignment = _device->_pMetalFeatures->mtlBufferAlignment;
|
_byteAlignment = _device->_pMetalFeatures->mtlBufferAlignment;
|
||||||
_byteCount = pCreateInfo->size;
|
_byteCount = pCreateInfo->size;
|
||||||
|
|
||||||
|
for (const auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
|
||||||
|
switch (next->sType) {
|
||||||
|
case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO: {
|
||||||
|
auto* pExtMemInfo = (const VkExternalMemoryBufferCreateInfo*)next;
|
||||||
|
initExternalMemory(pExtMemInfo->handleTypes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MVKBuffer::initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes) {
|
||||||
|
if (mvkIsOnlyAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR)) {
|
||||||
|
_externalMemoryHandleTypes = handleTypes;
|
||||||
|
auto& xmProps = _device->getPhysicalDevice()->getExternalBufferProperties(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR);
|
||||||
|
_requiresDedicatedMemoryAllocation = _requiresDedicatedMemoryAllocation || mvkIsAnyFlagEnabled(xmProps.externalMemoryFeatures, VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
|
||||||
|
} else {
|
||||||
|
setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateBuffer(): Only external memory handle type VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR is supported."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKBuffer::~MVKBuffer() {
|
MVKBuffer::~MVKBuffer() {
|
||||||
|
@ -283,6 +283,12 @@ public:
|
|||||||
/** Returns whether this is a unified memory device. */
|
/** Returns whether this is a unified memory device. */
|
||||||
bool getHasUnifiedMemory();
|
bool getHasUnifiedMemory();
|
||||||
|
|
||||||
|
/** Returns the external memory properties supported for buffers for the handle type. */
|
||||||
|
VkExternalMemoryProperties& getExternalBufferProperties(VkExternalMemoryHandleTypeFlagBits handleType);
|
||||||
|
|
||||||
|
/** Returns the external memory properties supported for images for the handle type. */
|
||||||
|
VkExternalMemoryProperties& getExternalImageProperties(VkExternalMemoryHandleTypeFlagBits handleType);
|
||||||
|
|
||||||
|
|
||||||
#pragma mark Metal
|
#pragma mark Metal
|
||||||
|
|
||||||
@ -337,6 +343,7 @@ protected:
|
|||||||
uint64_t getVRAMSize();
|
uint64_t getVRAMSize();
|
||||||
uint64_t getRecommendedMaxWorkingSetSize();
|
uint64_t getRecommendedMaxWorkingSetSize();
|
||||||
uint64_t getCurrentAllocatedSize();
|
uint64_t getCurrentAllocatedSize();
|
||||||
|
void initExternalMemoryProperties();
|
||||||
void initExtensions();
|
void initExtensions();
|
||||||
MVKVector<MVKQueueFamily*>& getQueueFamilies();
|
MVKVector<MVKQueueFamily*>& getQueueFamilies();
|
||||||
void initPipelineCacheUUID();
|
void initPipelineCacheUUID();
|
||||||
@ -344,9 +351,6 @@ protected:
|
|||||||
uint64_t getSpirvCrossRevision();
|
uint64_t getSpirvCrossRevision();
|
||||||
bool getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo);
|
bool getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo);
|
||||||
void populate(VkPhysicalDeviceIDProperties* pDevIdProps);
|
void populate(VkPhysicalDeviceIDProperties* pDevIdProps);
|
||||||
void populate(VkExternalMemoryProperties& xmProps,
|
|
||||||
VkExternalMemoryHandleTypeFlagBits handleType,
|
|
||||||
VkExternalMemoryHandleTypeFlagBits supportedHandleType);
|
|
||||||
void logGPUInfo();
|
void logGPUInfo();
|
||||||
|
|
||||||
id<MTLDevice> _mtlDevice;
|
id<MTLDevice> _mtlDevice;
|
||||||
@ -364,6 +368,8 @@ protected:
|
|||||||
uint32_t _hostCoherentMemoryTypes;
|
uint32_t _hostCoherentMemoryTypes;
|
||||||
uint32_t _privateMemoryTypes;
|
uint32_t _privateMemoryTypes;
|
||||||
uint32_t _lazilyAllocatedMemoryTypes;
|
uint32_t _lazilyAllocatedMemoryTypes;
|
||||||
|
VkExternalMemoryProperties _mtlBufferExternalMemoryProperties;
|
||||||
|
VkExternalMemoryProperties _mtlTextureExternalMemoryProperties;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -419,10 +419,7 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImage
|
|||||||
for (auto* nextProps = (VkBaseOutStructure*)pImageFormatProperties->pNext; nextProps; nextProps = nextProps->pNext) {
|
for (auto* nextProps = (VkBaseOutStructure*)pImageFormatProperties->pNext; nextProps; nextProps = nextProps->pNext) {
|
||||||
if (nextProps->sType == VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES) {
|
if (nextProps->sType == VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES) {
|
||||||
auto* pExtImgFmtProps = (VkExternalImageFormatProperties*)nextProps;
|
auto* pExtImgFmtProps = (VkExternalImageFormatProperties*)nextProps;
|
||||||
|
pExtImgFmtProps->externalMemoryProperties = getExternalImageProperties(pExtImgFmtInfo->handleType);
|
||||||
// TODO: This is an inoperable placeholder until VK_KHR_external_memory_metal is ratified and implemented
|
|
||||||
const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
|
|
||||||
populate(pExtImgFmtProps->externalMemoryProperties, pExtImgFmtInfo->handleType, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -482,24 +479,22 @@ bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageForma
|
|||||||
|
|
||||||
void MVKPhysicalDevice::getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
|
void MVKPhysicalDevice::getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
|
||||||
VkExternalBufferProperties* pExternalBufferProperties) {
|
VkExternalBufferProperties* pExternalBufferProperties) {
|
||||||
|
pExternalBufferProperties->externalMemoryProperties = getExternalBufferProperties(pExternalBufferInfo->handleType);
|
||||||
// TODO: This is an inoperable placeholder until VK_KHR_external_memory_metal is ratified and implemented
|
|
||||||
const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
|
|
||||||
populate(pExternalBufferProperties->externalMemoryProperties, pExternalBufferInfo->handleType, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the handleType is the supported handle type, populates xmProps accordingly, otherwise xmProps is cleared.
|
static VkExternalMemoryProperties _emptyExtMemProps = {};
|
||||||
void MVKPhysicalDevice::populate(VkExternalMemoryProperties& xmProps,
|
|
||||||
VkExternalMemoryHandleTypeFlagBits handleType,
|
VkExternalMemoryProperties& MVKPhysicalDevice::getExternalBufferProperties(VkExternalMemoryHandleTypeFlagBits handleType) {
|
||||||
VkExternalMemoryHandleTypeFlagBits supportedHandleType) {
|
switch (handleType) {
|
||||||
if (handleType == supportedHandleType) {
|
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR: return _mtlBufferExternalMemoryProperties;
|
||||||
xmProps.externalMemoryFeatures = (VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
|
default: return _emptyExtMemProps;
|
||||||
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
|
}
|
||||||
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT);
|
}
|
||||||
xmProps.exportFromImportedHandleTypes = supportedHandleType;
|
|
||||||
xmProps.compatibleHandleTypes = supportedHandleType;
|
VkExternalMemoryProperties& MVKPhysicalDevice::getExternalImageProperties(VkExternalMemoryHandleTypeFlagBits handleType) {
|
||||||
} else {
|
switch (handleType) {
|
||||||
mvkClear(&xmProps);
|
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR: return _mtlTextureExternalMemoryProperties;
|
||||||
|
default: return _emptyExtMemProps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,8 +842,9 @@ MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtl
|
|||||||
initMetalFeatures(); // Call first.
|
initMetalFeatures(); // Call first.
|
||||||
initFeatures(); // Call second.
|
initFeatures(); // Call second.
|
||||||
initProperties(); // Call third.
|
initProperties(); // Call third.
|
||||||
initMemoryProperties();
|
|
||||||
initExtensions();
|
initExtensions();
|
||||||
|
initMemoryProperties();
|
||||||
|
initExternalMemoryProperties();
|
||||||
logGPUInfo();
|
logGPUInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1973,6 +1969,23 @@ uint64_t MVKPhysicalDevice::getCurrentAllocatedSize() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MVKPhysicalDevice::initExternalMemoryProperties() {
|
||||||
|
|
||||||
|
// Buffers
|
||||||
|
_mtlBufferExternalMemoryProperties.externalMemoryFeatures = (VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
|
||||||
|
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
|
||||||
|
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT);
|
||||||
|
_mtlBufferExternalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR;
|
||||||
|
_mtlBufferExternalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR;
|
||||||
|
|
||||||
|
// Images
|
||||||
|
_mtlTextureExternalMemoryProperties.externalMemoryFeatures = (VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
|
||||||
|
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
|
||||||
|
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT);
|
||||||
|
_mtlTextureExternalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
|
||||||
|
_mtlTextureExternalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
void MVKPhysicalDevice::initExtensions() {
|
void MVKPhysicalDevice::initExtensions() {
|
||||||
MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_supportedExtensions;
|
MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_supportedExtensions;
|
||||||
pWritableExtns->disableAllButEnabledDeviceExtensions();
|
pWritableExtns->disableAllButEnabledDeviceExtensions();
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
class MVKBuffer;
|
class MVKBuffer;
|
||||||
class MVKImage;
|
class MVKImage;
|
||||||
|
|
||||||
|
// TODO: These are inoperable placeholders until VK_KHR_external_memory_metal defines them properly
|
||||||
|
static const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
|
||||||
|
static const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark MVKDeviceMemory
|
#pragma mark MVKDeviceMemory
|
||||||
|
|
||||||
@ -141,6 +145,7 @@ protected:
|
|||||||
bool ensureHostMemory();
|
bool ensureHostMemory();
|
||||||
void freeHostMemory();
|
void freeHostMemory();
|
||||||
MVKResource* getDedicatedResource();
|
MVKResource* getDedicatedResource();
|
||||||
|
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
||||||
|
|
||||||
MVKVectorInline<MVKBuffer*, 4> _buffers;
|
MVKVectorInline<MVKBuffer*, 4> _buffers;
|
||||||
MVKVectorInline<MVKImage*, 4> _images;
|
MVKVectorInline<MVKImage*, 4> _images;
|
||||||
|
@ -266,10 +266,7 @@ void MVKDeviceMemory::freeHostMemory() {
|
|||||||
|
|
||||||
MVKResource* MVKDeviceMemory::getDedicatedResource() {
|
MVKResource* MVKDeviceMemory::getDedicatedResource() {
|
||||||
MVKAssert(_isDedicated, "This method should only be called on dedicated allocations!");
|
MVKAssert(_isDedicated, "This method should only be called on dedicated allocations!");
|
||||||
if (_buffers.empty())
|
return _buffers.empty() ? (MVKResource*)_images[0] : (MVKResource*)_buffers[0];
|
||||||
return _images[0];
|
|
||||||
else
|
|
||||||
return _buffers[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
||||||
@ -284,22 +281,28 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
|||||||
|
|
||||||
VkImage dedicatedImage = VK_NULL_HANDLE;
|
VkImage dedicatedImage = VK_NULL_HANDLE;
|
||||||
VkBuffer dedicatedBuffer = VK_NULL_HANDLE;
|
VkBuffer dedicatedBuffer = VK_NULL_HANDLE;
|
||||||
auto* next = (VkStructureType*)pAllocateInfo->pNext;
|
VkExternalMemoryHandleTypeFlags handleTypes = 0;
|
||||||
while (next) {
|
for (const auto* next = (const VkBaseInStructure*)pAllocateInfo->pNext; next; next = next->pNext) {
|
||||||
switch (*next) {
|
switch (next->sType) {
|
||||||
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: {
|
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: {
|
||||||
auto* pDedicatedInfo = (VkMemoryDedicatedAllocateInfo*)next;
|
auto* pDedicatedInfo = (VkMemoryDedicatedAllocateInfo*)next;
|
||||||
dedicatedImage = pDedicatedInfo->image;
|
dedicatedImage = pDedicatedInfo->image;
|
||||||
dedicatedBuffer = pDedicatedInfo->buffer;
|
dedicatedBuffer = pDedicatedInfo->buffer;
|
||||||
next = (VkStructureType*)pDedicatedInfo->pNext;
|
_isDedicated = dedicatedImage || dedicatedBuffer;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: {
|
||||||
next = (VkStructureType*)((VkMemoryAllocateInfo*)next)->pNext;
|
auto* pExpMemInfo = (VkExportMemoryAllocateInfo*)next;
|
||||||
break;
|
handleTypes = pExpMemInfo->handleTypes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initExternalMemory(handleTypes); // After setting _isDedicated
|
||||||
|
|
||||||
// "Dedicated" means this memory can only be used for this image or buffer.
|
// "Dedicated" means this memory can only be used for this image or buffer.
|
||||||
if (dedicatedImage) {
|
if (dedicatedImage) {
|
||||||
#if MVK_MACOS
|
#if MVK_MACOS
|
||||||
@ -316,14 +319,16 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_isDedicated = true;
|
|
||||||
_images.push_back((MVKImage*)dedicatedImage);
|
_images.push_back((MVKImage*)dedicatedImage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we can, create a MTLHeap. This should happen before creating the buffer
|
if (dedicatedBuffer) {
|
||||||
// allowing us to map its contents.
|
_buffers.push_back((MVKBuffer*)dedicatedBuffer);
|
||||||
if (!dedicatedImage && !dedicatedBuffer) {
|
}
|
||||||
|
|
||||||
|
// If we can, create a MTLHeap. This should happen before creating the buffer, allowing us to map its contents.
|
||||||
|
if ( !_isDedicated ) {
|
||||||
if (!ensureMTLHeap()) {
|
if (!ensureMTLHeap()) {
|
||||||
setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate VkDeviceMemory of size %llu bytes.", _allocationSize));
|
setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate VkDeviceMemory of size %llu bytes.", _allocationSize));
|
||||||
return;
|
return;
|
||||||
@ -334,10 +339,26 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
|||||||
if (isMemoryHostCoherent() && !ensureMTLBuffer() ) {
|
if (isMemoryHostCoherent() && !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));
|
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));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dedicatedBuffer) {
|
void MVKDeviceMemory::initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes) {
|
||||||
_isDedicated = true;
|
if ( !handleTypes ) { return; }
|
||||||
_buffers.push_back((MVKBuffer*)dedicatedBuffer);
|
|
||||||
|
if ( !mvkIsOnlyAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR | VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR) ) {
|
||||||
|
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "vkAllocateMemory(): Only external memory handle types VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR or VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR are supported."));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool requiresDedicated = false;
|
||||||
|
if (mvkIsAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR)) {
|
||||||
|
auto& xmProps = _device->getPhysicalDevice()->getExternalBufferProperties(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR);
|
||||||
|
requiresDedicated = requiresDedicated || mvkIsAnyFlagEnabled(xmProps.externalMemoryFeatures, VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
|
||||||
|
}
|
||||||
|
if (mvkIsAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR)) {
|
||||||
|
auto& xmProps = _device->getPhysicalDevice()->getExternalImageProperties(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR);
|
||||||
|
requiresDedicated = requiresDedicated || mvkIsAnyFlagEnabled(xmProps.externalMemoryFeatures, VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
|
||||||
|
}
|
||||||
|
if (requiresDedicated && !_isDedicated) {
|
||||||
|
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "vkAllocateMemory(): External memory requires a dedicated VkBuffer or VkImage."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ protected:
|
|||||||
bool validateUseTexelBuffer();
|
bool validateUseTexelBuffer();
|
||||||
void initSubresources(const VkImageCreateInfo* pCreateInfo);
|
void initSubresources(const VkImageCreateInfo* pCreateInfo);
|
||||||
void initSubresourceLayout(MVKImageSubresource& imgSubRez);
|
void initSubresourceLayout(MVKImageSubresource& imgSubRez);
|
||||||
|
void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
|
||||||
id<MTLTexture> newMTLTexture();
|
id<MTLTexture> newMTLTexture();
|
||||||
void releaseMTLTexture();
|
void releaseMTLTexture();
|
||||||
void releaseIOSurface();
|
void releaseIOSurface();
|
||||||
|
@ -182,8 +182,9 @@ VkResult MVKImage::getMemoryRequirements(const void*, VkMemoryRequirements2* pMe
|
|||||||
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
|
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
|
||||||
auto* dedicatedReqs = (VkMemoryDedicatedRequirements*)next;
|
auto* dedicatedReqs = (VkMemoryDedicatedRequirements*)next;
|
||||||
bool writable = mvkIsAnyFlagEnabled(_usage, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
bool writable = mvkIsAnyFlagEnabled(_usage, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
||||||
dedicatedReqs->prefersDedicatedAllocation = !_usesTexelBuffer && (writable || !_device->_pMetalFeatures->placementHeaps);
|
dedicatedReqs->requiresDedicatedAllocation = _requiresDedicatedMemoryAllocation;
|
||||||
dedicatedReqs->requiresDedicatedAllocation = VK_FALSE;
|
dedicatedReqs->prefersDedicatedAllocation = (dedicatedReqs->requiresDedicatedAllocation ||
|
||||||
|
(!_usesTexelBuffer && (writable || !_device->_pMetalFeatures->placementHeaps)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -615,6 +616,18 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
|||||||
}
|
}
|
||||||
|
|
||||||
initSubresources(pCreateInfo);
|
initSubresources(pCreateInfo);
|
||||||
|
|
||||||
|
for (const auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
|
||||||
|
switch (next->sType) {
|
||||||
|
case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO: {
|
||||||
|
auto* pExtMemInfo = (const VkExternalMemoryImageCreateInfo*)next;
|
||||||
|
initExternalMemory(pExtMemInfo->handleTypes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSampleCountFlagBits MVKImage::validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment) {
|
VkSampleCountFlagBits MVKImage::validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment) {
|
||||||
@ -784,6 +797,16 @@ void MVKImage::initSubresourceLayout(MVKImageSubresource& imgSubRez) {
|
|||||||
layout.depthPitch = bytesPerLayerCurrLevel;
|
layout.depthPitch = bytesPerLayerCurrLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MVKImage::initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes) {
|
||||||
|
if (mvkIsOnlyAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR)) {
|
||||||
|
_externalMemoryHandleTypes = handleTypes;
|
||||||
|
auto& xmProps = _device->getPhysicalDevice()->getExternalImageProperties(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR);
|
||||||
|
_requiresDedicatedMemoryAllocation = _requiresDedicatedMemoryAllocation || mvkIsAnyFlagEnabled(xmProps.externalMemoryFeatures, VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
|
||||||
|
} else {
|
||||||
|
setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage(): Only external memory handle type VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR is supported."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MVKImage::~MVKImage() {
|
MVKImage::~MVKImage() {
|
||||||
if (_deviceMemory) { _deviceMemory->removeImage(this); }
|
if (_deviceMemory) { _deviceMemory->removeImage(this); }
|
||||||
releaseMTLTexture();
|
releaseMTLTexture();
|
||||||
|
@ -88,4 +88,6 @@ protected:
|
|||||||
VkDeviceSize _deviceMemoryOffset = 0;
|
VkDeviceSize _deviceMemoryOffset = 0;
|
||||||
VkDeviceSize _byteCount = 0;
|
VkDeviceSize _byteCount = 0;
|
||||||
VkDeviceSize _byteAlignment = 0;
|
VkDeviceSize _byteAlignment = 0;
|
||||||
|
VkExternalMemoryHandleTypeFlags _externalMemoryHandleTypes = 0;
|
||||||
|
bool _requiresDedicatedMemoryAllocation = false;
|
||||||
};
|
};
|
||||||
|
@ -46,6 +46,7 @@ MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION, DEVICE)
|
|||||||
MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, DEVICE)
|
MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, DEVICE)
|
||||||
MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, DEVICE)
|
MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, DEVICE)
|
||||||
MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, INSTANCE)
|
MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, INSTANCE)
|
||||||
|
MVK_EXTENSION(KHR_external_memory, KHR_EXTERNAL_MEMORY, DEVICE)
|
||||||
MVK_EXTENSION(KHR_external_memory_capabilities, KHR_EXTERNAL_MEMORY_CAPABILITIES, INSTANCE)
|
MVK_EXTENSION(KHR_external_memory_capabilities, KHR_EXTERNAL_MEMORY_CAPABILITIES, INSTANCE)
|
||||||
MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, DEVICE)
|
MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, DEVICE)
|
||||||
MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, INSTANCE)
|
MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, INSTANCE)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user