Merge pull request #872 from billhollings/master

Add support for VK_KHR_external_memory extension.
This commit is contained in:
Bill Hollings 2020-05-06 21:40:50 -04:00 committed by GitHub
commit 5fe0b91fc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 531 additions and 388 deletions

View File

@ -19,6 +19,12 @@ MoltenVK 1.0.42
Released TBD Released TBD
- Add support for extensions:
- `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.
- 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.
- `vkQueuePresentKHR()` returns a `VkResult` for each swapchain. - `vkQueuePresentKHR()` returns a `VkResult` for each swapchain.

View File

@ -261,18 +261,17 @@ VkResult MVKCmdPushDescriptorSet::setContent(MVKCommandBuffer* cmdBuff,
} }
if (mvkDvc->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) { if (mvkDvc->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) {
const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr; const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr;
for (auto* next = (VkWriteDescriptorSetInlineUniformBlockEXT*)descWrite.pNext; next; next = (VkWriteDescriptorSetInlineUniformBlockEXT*)next->pNext) for (const auto* next = (VkBaseInStructure*)descWrite.pNext; next; next = next->pNext) {
{
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: { case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: {
pInlineUniformBlock = next; pInlineUniformBlock = (VkWriteDescriptorSetInlineUniformBlockEXT*)next;
break; break;
} }
default: default:
break; break;
} }
} }
if (pInlineUniformBlock != nullptr) { if (pInlineUniformBlock) {
auto *pNewInlineUniformBlock = new VkWriteDescriptorSetInlineUniformBlockEXT(*pInlineUniformBlock); auto *pNewInlineUniformBlock = new VkWriteDescriptorSetInlineUniformBlockEXT(*pInlineUniformBlock);
pNewInlineUniformBlock->pNext = nullptr; // clear pNext just in case, no other extensions are supported at this time pNewInlineUniformBlock->pNext = nullptr; // clear pNext just in case, no other extensions are supported at this time
descWrite.pNext = pNewInlineUniformBlock; descWrite.pNext = pNewInlineUniformBlock;
@ -300,11 +299,10 @@ void MVKCmdPushDescriptorSet::clearDescriptorWrites() {
if (descWrite.pTexelBufferView) { delete[] descWrite.pTexelBufferView; } if (descWrite.pTexelBufferView) { delete[] descWrite.pTexelBufferView; }
const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr; const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr;
for (auto* next = (VkWriteDescriptorSetInlineUniformBlockEXT*)descWrite.pNext; next; next = (VkWriteDescriptorSetInlineUniformBlockEXT*)next->pNext) for (const auto* next = (VkBaseInStructure*)descWrite.pNext; next; next = next->pNext) {
{
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: { case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: {
pInlineUniformBlock = next; pInlineUniformBlock = (VkWriteDescriptorSetInlineUniformBlockEXT*)next;
break; break;
} }
default: default:

View File

@ -48,6 +48,9 @@ public:
/** Binds this resource to the specified offset within the specified memory allocation. */ /** Binds this resource to the specified offset within the specified memory allocation. */
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override; VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override;
/** Binds this resource to the specified offset within the specified memory allocation. */
VkResult bindDeviceMemory2(const VkBindBufferMemoryInfo* pBindInfo);
/** Applies the specified global memory barrier. */ /** Applies the specified global memory barrier. */
void applyMemoryBarrier(VkPipelineStageFlags srcStageMask, void applyMemoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask, VkPipelineStageFlags dstStageMask,
@ -92,6 +95,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;

View File

@ -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:
@ -93,6 +93,10 @@ VkResult MVKBuffer::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOf
return _deviceMemory ? _deviceMemory->addBuffer(this) : VK_SUCCESS; return _deviceMemory ? _deviceMemory->addBuffer(this) : VK_SUCCESS;
} }
VkResult MVKBuffer::bindDeviceMemory2(const VkBindBufferMemoryInfo* pBindInfo) {
return bindDeviceMemory((MVKDeviceMemory*)pBindInfo->memory, pBindInfo->memoryOffset);
}
void MVKBuffer::applyMemoryBarrier(VkPipelineStageFlags srcStageMask, void MVKBuffer::applyMemoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask, VkPipelineStageFlags dstStageMask,
VkMemoryBarrier* pMemoryBarrier, VkMemoryBarrier* pMemoryBarrier,
@ -192,6 +196,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() {

View File

@ -109,11 +109,10 @@ void MVKDescriptorSetLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder,
const VkBufferView* pTexelBufferView = descWrite.pTexelBufferView; const VkBufferView* pTexelBufferView = descWrite.pTexelBufferView;
const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr; const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr;
if (_device->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) { if (_device->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) {
for (auto* next = (VkWriteDescriptorSetInlineUniformBlockEXT*)descWrite.pNext; next; next = (VkWriteDescriptorSetInlineUniformBlockEXT*)next->pNext) for (const auto* next = (VkBaseInStructure*)descWrite.pNext; next; next = next->pNext) {
{
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: { case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: {
pInlineUniformBlock = next; pInlineUniformBlock = (VkWriteDescriptorSetInlineUniformBlockEXT*)next;
break; break;
} }
default: default:
@ -689,11 +688,10 @@ void mvkUpdateDescriptorSets(uint32_t writeCount,
const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr; const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr;
if (dstSet->getDevice()->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) { if (dstSet->getDevice()->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) {
for (auto* next = (VkWriteDescriptorSetInlineUniformBlockEXT*)pDescWrite->pNext; next; next = (VkWriteDescriptorSetInlineUniformBlockEXT*)next->pNext) for (const auto* next = (VkBaseInStructure*)pDescWrite->pNext; next; next = next->pNext) {
{
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: { case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: {
pInlineUniformBlock = next; pInlineUniformBlock = (VkWriteDescriptorSetInlineUniformBlockEXT*)next;
break; break;
} }
default: default:

View File

@ -117,12 +117,9 @@ public:
void getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties); void getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties);
/** Populates the specified structure with the format properties of this device. */ /** Populates the specified structure with the format properties of this device. */
void getFormatProperties(VkFormat format, VkFormatProperties2KHR* pFormatProperties); void getFormatProperties(VkFormat format, VkFormatProperties2* pFormatProperties);
/** /** Populates the image format properties supported on this device. */
* Populates the specified structure with the image format properties
* supported for the specified image characteristics on this device.
*/
VkResult getImageFormatProperties(VkFormat format, VkResult getImageFormatProperties(VkFormat format,
VkImageType type, VkImageType type,
VkImageTiling tiling, VkImageTiling tiling,
@ -130,12 +127,13 @@ public:
VkImageCreateFlags flags, VkImageCreateFlags flags,
VkImageFormatProperties* pImageFormatProperties); VkImageFormatProperties* pImageFormatProperties);
/** /** Populates the image format properties supported on this device. */
* Populates the specified structure with the image format properties VkResult getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
* supported for the specified image characteristics on this device. VkImageFormatProperties2* pImageFormatProperties);
*/
VkResult getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, /** Populates the external buffer properties supported on this device. */
VkImageFormatProperties2KHR* pImageFormatProperties); void getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
VkExternalBufferProperties* pExternalBufferProperties);
#pragma mark Surfaces #pragma mark Surfaces
@ -244,13 +242,13 @@ public:
#pragma mark Memory models #pragma mark Memory models
/** Returns a pointer to the memory characteristics of this device. */ /** Returns a pointer to the memory characteristics of this device. */
inline const VkPhysicalDeviceMemoryProperties* getPhysicalDeviceMemoryProperties() { return &_memoryProperties; } inline const VkPhysicalDeviceMemoryProperties* getMemoryProperties() { return &_memoryProperties; }
/** Populates the specified memory properties with the memory characteristics of this device. */ /** Populates the specified memory properties with the memory characteristics of this device. */
VkResult getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties); VkResult getMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties);
/** Populates the specified memory properties with the memory characteristics of this device. */ /** Populates the specified memory properties with the memory characteristics of this device. */
VkResult getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties); VkResult getMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
/** /**
* Returns a bit mask of all memory type indices. * Returns a bit mask of all memory type indices.
@ -285,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
@ -339,12 +343,14 @@ 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();
uint32_t getHighestMTLFeatureSet(); uint32_t getHighestMTLFeatureSet();
uint64_t getSpirvCrossRevision(); uint64_t getSpirvCrossRevision();
bool getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo); bool getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo);
void populate(VkPhysicalDeviceIDProperties* pDevIdProps);
void logGPUInfo(); void logGPUInfo();
id<MTLDevice> _mtlDevice; id<MTLDevice> _mtlDevice;
@ -362,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;
}; };

View File

@ -62,11 +62,10 @@ VkResult MVKPhysicalDevice::getExtensionProperties(const char* pLayerName, uint3
} }
void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures* features) { void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures* features) {
if (features) { *features = _features; } *features = _features;
} }
void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) { void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
if (features) {
features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
features->features = _features; features->features = _features;
for (auto* next = (VkBaseOutStructure*)features->pNext; next; next = next->pNext) { for (auto* next = (VkBaseOutStructure*)features->pNext; next; next = next->pNext) {
@ -156,14 +155,12 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
} }
} }
} }
}
void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties* properties) { void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties* properties) {
if (properties) { *properties = _properties; } *properties = _properties;
} }
void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) { void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
if (properties) {
properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties->properties = _properties; properties->properties = _properties;
for (auto* next = (VkBaseOutStructure*)properties->pNext; next; next = next->pNext) { for (auto* next = (VkBaseOutStructure*)properties->pNext; next; next = next->pNext) {
@ -198,6 +195,10 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32; divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32;
break; break;
} }
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
populate((VkPhysicalDeviceIDProperties*)next);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_EXTX: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_EXTX: {
auto* portabilityProps = (VkPhysicalDevicePortabilitySubsetPropertiesEXTX*)next; auto* portabilityProps = (VkPhysicalDevicePortabilitySubsetPropertiesEXTX*)next;
portabilityProps->minVertexInputBindingStrideAlignment = 4; portabilityProps->minVertexInputBindingStrideAlignment = 4;
@ -208,21 +209,70 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
} }
} }
} }
// Populates the device ID properties structure
void MVKPhysicalDevice::populate(VkPhysicalDeviceIDProperties* pDevIdProps) {
uint8_t* uuid;
size_t uuidComponentOffset;
// ---- Device ID ----------------------------------------------
uuid = pDevIdProps->deviceUUID;
uuidComponentOffset = 0;
mvkClear(uuid, VK_UUID_SIZE);
// First 4 bytes contains GPU vendor ID
uint32_t vendorID = _properties.vendorID;
*(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(vendorID);
uuidComponentOffset += sizeof(vendorID);
// Next 4 bytes contains GPU device ID
uint32_t deviceID = _properties.deviceID;
*(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(deviceID);
uuidComponentOffset += sizeof(deviceID);
// Last 8 bytes contain the GPU registry ID
uint64_t regID = mvkGetRegistryID(_mtlDevice);
*(uint64_t*)&uuid[uuidComponentOffset] = NSSwapHostLongLongToBig(regID);
uuidComponentOffset += sizeof(regID);
// ---- Driver ID ----------------------------------------------
uuid = pDevIdProps->driverUUID;
uuidComponentOffset = 0;
mvkClear(uuid, VK_UUID_SIZE);
// First 4 bytes contains MoltenVK prefix
const char* mvkPfx = "MVK";
size_t mvkPfxLen = strlen(mvkPfx);
mvkCopy(&uuid[uuidComponentOffset], (uint8_t*)mvkPfx, mvkPfxLen);
uuidComponentOffset += mvkPfxLen + 1;
// Next 4 bytes contains MoltenVK version
uint32_t mvkVersion = MVK_VERSION;
*(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(mvkVersion);
uuidComponentOffset += sizeof(mvkVersion);
// Next 4 bytes contains highest Metal feature set supported by this device
uint32_t mtlFeatSet = getHighestMTLFeatureSet();
*(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(mtlFeatSet);
uuidComponentOffset += sizeof(mtlFeatSet);
// ---- LUID ignored for Metal devices ------------------------
mvkClear(pDevIdProps->deviceLUID, VK_LUID_SIZE);
pDevIdProps->deviceNodeMask = 0;
pDevIdProps->deviceLUIDValid = VK_FALSE;
} }
void MVKPhysicalDevice::getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties) { void MVKPhysicalDevice::getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties) {
if (pFormatProperties) {
*pFormatProperties = _pixelFormats.getVkFormatProperties(format); *pFormatProperties = _pixelFormats.getVkFormatProperties(format);
} }
}
void MVKPhysicalDevice::getFormatProperties(VkFormat format, void MVKPhysicalDevice::getFormatProperties(VkFormat format, VkFormatProperties2KHR* pFormatProperties) {
VkFormatProperties2KHR* pFormatProperties) {
if (pFormatProperties) {
pFormatProperties->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR; pFormatProperties->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR;
pFormatProperties->formatProperties = _pixelFormats.getVkFormatProperties(format); pFormatProperties->formatProperties = _pixelFormats.getVkFormatProperties(format);
} }
}
VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format,
VkImageType type, VkImageType type,
@ -357,32 +407,41 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format,
return VK_SUCCESS; return VK_SUCCESS;
} }
VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo, VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
VkImageFormatProperties2KHR* pImageFormatProperties) { VkImageFormatProperties2* pImageFormatProperties) {
if ( !pImageFormatInfo || pImageFormatInfo->sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR ) { for (const auto* nextInfo = (VkBaseInStructure*)pImageFormatInfo->pNext; nextInfo; nextInfo = nextInfo->pNext) {
return VK_ERROR_FORMAT_NOT_SUPPORTED; switch (nextInfo->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: {
// Return information about external memory support for MTLTexture.
// Search VkImageFormatProperties2 for the corresponding VkExternalImageFormatProperties and populate it.
auto* pExtImgFmtInfo = (VkPhysicalDeviceExternalImageFormatInfo*)nextInfo;
for (auto* nextProps = (VkBaseOutStructure*)pImageFormatProperties->pNext; nextProps; nextProps = nextProps->pNext) {
if (nextProps->sType == VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES) {
auto* pExtImgFmtProps = (VkExternalImageFormatProperties*)nextProps;
pExtImgFmtProps->externalMemoryProperties = getExternalImageProperties(pExtImgFmtInfo->handleType);
}
}
break;
}
default:
break;
}
} }
if ( !_pixelFormats.isSupported(pImageFormatInfo->format) ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } if ( !_pixelFormats.isSupported(pImageFormatInfo->format) ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; }
if ( !getImageViewIsSupported(pImageFormatInfo) ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } if ( !getImageViewIsSupported(pImageFormatInfo) ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; }
if (pImageFormatProperties) {
pImageFormatProperties->sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
return getImageFormatProperties(pImageFormatInfo->format, pImageFormatInfo->type, return getImageFormatProperties(pImageFormatInfo->format, pImageFormatInfo->type,
pImageFormatInfo->tiling, pImageFormatInfo->usage, pImageFormatInfo->tiling, pImageFormatInfo->usage,
pImageFormatInfo->flags, pImageFormatInfo->flags,
&pImageFormatProperties->imageFormatProperties); &pImageFormatProperties->imageFormatProperties);
} }
return VK_SUCCESS;
}
// If the image format info links portability image view info, test if an image view of that configuration is supported // If the image format info links portability image view info, test if an image view of that configuration is supported
bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo) { bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo) {
auto* next = (MVKVkAPIStructHeader*)pImageFormatInfo->pNext; for (const auto* next = (VkBaseInStructure*)pImageFormatInfo->pNext; next; next = next->pNext) {
while (next) {
switch ((uint32_t)next->sType) { switch ((uint32_t)next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_SUPPORT_EXTX: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_SUPPORT_EXTX: {
auto* portImgViewInfo = (VkPhysicalDeviceImageViewSupportEXTX*)next; auto* portImgViewInfo = (VkPhysicalDeviceImageViewSupportEXTX*)next;
@ -390,7 +449,7 @@ bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageForma
// Create an image view and test whether it could be configured // Create an image view and test whether it could be configured
VkImageViewCreateInfo viewInfo = { VkImageViewCreateInfo viewInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = (VkStructureType*)portImgViewInfo->pNext, .pNext = portImgViewInfo->pNext,
.flags = portImgViewInfo->flags, .flags = portImgViewInfo->flags,
.image = nullptr, .image = nullptr,
.viewType = portImgViewInfo->viewType, .viewType = portImgViewInfo->viewType,
@ -411,7 +470,6 @@ bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageForma
mtlPixFmt, useSwizzle) == VK_SUCCESS); mtlPixFmt, useSwizzle) == VK_SUCCESS);
} }
default: default:
next = (MVKVkAPIStructHeader*)next->pNext;
break; break;
} }
} }
@ -419,6 +477,27 @@ bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageForma
return true; return true;
} }
void MVKPhysicalDevice::getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
VkExternalBufferProperties* pExternalBufferProperties) {
pExternalBufferProperties->externalMemoryProperties = getExternalBufferProperties(pExternalBufferInfo->handleType);
}
static VkExternalMemoryProperties _emptyExtMemProps = {};
VkExternalMemoryProperties& MVKPhysicalDevice::getExternalBufferProperties(VkExternalMemoryHandleTypeFlagBits handleType) {
switch (handleType) {
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR: return _mtlBufferExternalMemoryProperties;
default: return _emptyExtMemProps;
}
}
VkExternalMemoryProperties& MVKPhysicalDevice::getExternalImageProperties(VkExternalMemoryHandleTypeFlagBits handleType) {
switch (handleType) {
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR: return _mtlTextureExternalMemoryProperties;
default: return _emptyExtMemProps;
}
}
#pragma mark Surfaces #pragma mark Surfaces
@ -722,13 +801,12 @@ VkResult MVKPhysicalDevice::getQueueFamilyProperties(uint32_t* pCount,
#pragma mark Memory models #pragma mark Memory models
/** Populates the specified memory properties with the memory characteristics of this device. */ /** Populates the specified memory properties with the memory characteristics of this device. */
VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties) { VkResult MVKPhysicalDevice::getMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
*pMemoryProperties = _memoryProperties; *pMemoryProperties = _memoryProperties;
return VK_SUCCESS; return VK_SUCCESS;
} }
VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties) { VkResult MVKPhysicalDevice::getMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
if (pMemoryProperties) {
pMemoryProperties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; pMemoryProperties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
pMemoryProperties->memoryProperties = _memoryProperties; pMemoryProperties->memoryProperties = _memoryProperties;
for (auto* next = (VkBaseOutStructure*)pMemoryProperties->pNext; next; next = next->pNext) { for (auto* next = (VkBaseOutStructure*)pMemoryProperties->pNext; next; next = next->pNext) {
@ -749,7 +827,6 @@ VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMe
break; break;
} }
} }
}
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -765,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();
} }
@ -1470,8 +1548,7 @@ void MVKPhysicalDevice::initGPUInfoProperties() {
if (regID) { if (regID) {
entry = IOServiceGetMatchingService(kIOMasterPortDefault, IORegistryEntryIDMatching(regID)); entry = IOServiceGetMatchingService(kIOMasterPortDefault, IORegistryEntryIDMatching(regID));
if (entry) { if (entry) {
// That returned the IOGraphicsAccelerator nub. Its parent, then, is the actual // That returned the IOGraphicsAccelerator nub. Its parent, then, is the actual PCI device.
// PCI device.
io_registry_entry_t parent; io_registry_entry_t parent;
if (IORegistryEntryGetParentEntry(entry, kIOServicePlane, &parent) == kIOReturnSuccess) { if (IORegistryEntryGetParentEntry(entry, kIOServicePlane, &parent) == kIOReturnSuccess) {
isFound = true; isFound = true;
@ -1665,7 +1742,7 @@ void MVKPhysicalDevice::initPipelineCacheUUID() {
*(uint32_t*)&_properties.pipelineCacheUUID[uuidComponentOffset] = NSSwapHostIntToBig(mvkVersion); *(uint32_t*)&_properties.pipelineCacheUUID[uuidComponentOffset] = NSSwapHostIntToBig(mvkVersion);
uuidComponentOffset += sizeof(mvkVersion); uuidComponentOffset += sizeof(mvkVersion);
// Next 4 bytes contains hightest Metal feature set supported by this device // Next 4 bytes contains highest Metal feature set supported by this device
uint32_t mtlFeatSet = getHighestMTLFeatureSet(); uint32_t mtlFeatSet = getHighestMTLFeatureSet();
*(uint32_t*)&_properties.pipelineCacheUUID[uuidComponentOffset] = NSSwapHostIntToBig(mtlFeatSet); *(uint32_t*)&_properties.pipelineCacheUUID[uuidComponentOffset] = NSSwapHostIntToBig(mtlFeatSet);
uuidComponentOffset += sizeof(mtlFeatSet); uuidComponentOffset += sizeof(mtlFeatSet);
@ -1892,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();
@ -2815,8 +2909,7 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
&pdFeats2.features.robustBufferAccess, 55); &pdFeats2.features.robustBufferAccess, 55);
} }
auto* next = (MVKVkAPIStructHeader*)pCreateInfo->pNext; for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
while (next) {
switch ((uint32_t)next->sType) { switch ((uint32_t)next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: {
auto* requestedFeatures = (VkPhysicalDeviceFeatures2*)next; auto* requestedFeatures = (VkPhysicalDeviceFeatures2*)next;
@ -2905,7 +2998,6 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
default: default:
break; break;
} }
next = (MVKVkAPIStructHeader*)next->pNext;
} }
} }

View File

@ -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;

View File

@ -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;
}
case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: {
auto* pExpMemInfo = (VkExportMemoryAllocateInfo*)next;
handleTypes = pExpMemInfo->handleTypes;
break; break;
} }
default: default:
next = (VkStructureType*)((VkMemoryAllocateInfo*)next)->pNext;
break; 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."));
} }
} }

View File

@ -130,6 +130,9 @@ public:
/** Binds this resource to the specified offset within the specified memory allocation. */ /** Binds this resource to the specified offset within the specified memory allocation. */
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override; VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override;
/** Binds this resource to the specified offset within the specified memory allocation. */
virtual VkResult bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo);
/** Applies the specified global memory barrier. */ /** Applies the specified global memory barrier. */
void applyMemoryBarrier(VkPipelineStageFlags srcStageMask, void applyMemoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask, VkPipelineStageFlags dstStageMask,
@ -235,6 +238,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();
@ -380,7 +384,7 @@ class MVKPeerSwapchainImage : public MVKSwapchainImage {
public: public:
/** Binds this resource according to the specified bind information. */ /** Binds this resource according to the specified bind information. */
VkResult bindDeviceMemory2(const void* pBindInfo) override; VkResult bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo) override;
#pragma mark Construction #pragma mark Construction

View File

@ -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:
@ -206,6 +207,10 @@ VkResult MVKImage::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOff
return _deviceMemory ? _deviceMemory->addImage(this) : VK_SUCCESS; return _deviceMemory ? _deviceMemory->addImage(this) : VK_SUCCESS;
} }
VkResult MVKImage::bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo) {
return bindDeviceMemory((MVKDeviceMemory*)pBindInfo->memory, pBindInfo->memoryOffset);
}
bool MVKImage::validateUseTexelBuffer() { bool MVKImage::validateUseTexelBuffer() {
VkExtent2D blockExt = getPixelFormats()->getBlockTexelSize(_mtlPixelFormat); VkExtent2D blockExt = getPixelFormats()->getBlockTexelSize(_mtlPixelFormat);
bool isUncompressed = blockExt.width == 1 && blockExt.height == 1; bool isUncompressed = blockExt.width == 1 && blockExt.height == 1;
@ -615,6 +620,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 +801,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();
@ -991,10 +1018,9 @@ MVKPresentableSwapchainImage::~MVKPresentableSwapchainImage() {
#pragma mark - #pragma mark -
#pragma mark MVKPeerSwapchainImage #pragma mark MVKPeerSwapchainImage
VkResult MVKPeerSwapchainImage::bindDeviceMemory2(const void* pBindInfo) { VkResult MVKPeerSwapchainImage::bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo) {
const auto* imageInfo = (const VkBindImageMemoryInfo*)pBindInfo;
const VkBindImageMemorySwapchainInfoKHR* swapchainInfo = nullptr; const VkBindImageMemorySwapchainInfoKHR* swapchainInfo = nullptr;
for (const auto* next = (const VkBaseInStructure*)imageInfo->pNext; next; next = next->pNext) { for (const auto* next = (const VkBaseInStructure*)pBindInfo->pNext; next; next = next->pNext) {
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR:
swapchainInfo = (const VkBindImageMemorySwapchainInfoKHR*)next; swapchainInfo = (const VkBindImageMemorySwapchainInfoKHR*)next;
@ -1002,11 +1028,9 @@ VkResult MVKPeerSwapchainImage::bindDeviceMemory2(const void* pBindInfo) {
default: default:
break; break;
} }
if (swapchainInfo) { break; }
}
if (!swapchainInfo) {
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
} }
if (!swapchainInfo) { return VK_ERROR_OUT_OF_DEVICE_MEMORY; }
_swapchainIndex = swapchainInfo->imageIndex; _swapchainIndex = swapchainInfo->imageIndex;
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -1114,17 +1138,14 @@ MVKImageView::MVKImageView(MVKDevice* device,
_image = (MVKImage*)pCreateInfo->image; _image = (MVKImage*)pCreateInfo->image;
_usage = _image->_usage; _usage = _image->_usage;
auto* next = (MVKVkAPIStructHeader*)pCreateInfo->pNext; for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
while (next) { switch (next->sType) {
switch ((uint32_t)next->sType) {
case VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO: { case VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO: {
auto* pViewUsageInfo = (VkImageViewUsageCreateInfo*)next; auto* pViewUsageInfo = (VkImageViewUsageCreateInfo*)next;
if (!(pViewUsageInfo->usage & ~_usage)) { _usage = pViewUsageInfo->usage; } if (!(pViewUsageInfo->usage & ~_usage)) { _usage = pViewUsageInfo->usage; }
next = (MVKVkAPIStructHeader*)next->pNext;
break; break;
} }
default: default:
next = (MVKVkAPIStructHeader*)next->pNext;
break; break;
} }
} }

View File

@ -383,8 +383,7 @@ void MVKInstance::initDebugCallbacks(const VkInstanceCreateInfo* pCreateInfo) {
_hasDebugUtilsMessengers = false; _hasDebugUtilsMessengers = false;
_debugReportCallbackLayerPrefix = getDriverLayer()->getName(); _debugReportCallbackLayerPrefix = getDriverLayer()->getName();
MVKVkAPIStructHeader* next = (MVKVkAPIStructHeader*)pCreateInfo->pNext; for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
while (next) {
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT: case VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT:
createDebugReportCallback((VkDebugReportCallbackCreateInfoEXT*)next, nullptr); createDebugReportCallback((VkDebugReportCallbackCreateInfoEXT*)next, nullptr);
@ -395,7 +394,6 @@ void MVKInstance::initDebugCallbacks(const VkInstanceCreateInfo* pCreateInfo) {
default: default:
break; break;
} }
next = (MVKVkAPIStructHeader*)next->pNext;
} }
} }

View File

@ -944,15 +944,12 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(MTLRenderPipelineDescriptor*
const SPIRVToMSLConversionConfiguration& shaderContext) { const SPIRVToMSLConversionConfiguration& shaderContext) {
// Collect extension structures // Collect extension structures
VkPipelineVertexInputDivisorStateCreateInfoEXT* pVertexInputDivisorState = nullptr; VkPipelineVertexInputDivisorStateCreateInfoEXT* pVertexInputDivisorState = nullptr;
auto* next = (MVKVkAPIStructHeader*)pVI->pNext; for (const auto* next = (VkBaseInStructure*)pVI->pNext; next; next = next->pNext) {
while (next) {
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT:
pVertexInputDivisorState = (VkPipelineVertexInputDivisorStateCreateInfoEXT*)next; pVertexInputDivisorState = (VkPipelineVertexInputDivisorStateCreateInfoEXT*)next;
next = (MVKVkAPIStructHeader*)pVertexInputDivisorState->pNext;
break; break;
default: default:
next = (MVKVkAPIStructHeader*)next->pNext;
break; break;
} }
} }
@ -1032,15 +1029,12 @@ void MVKGraphicsPipeline::addTessellationToPipeline(MTLRenderPipelineDescriptor*
VkPipelineTessellationDomainOriginStateCreateInfo* pTessDomainOriginState = nullptr; VkPipelineTessellationDomainOriginStateCreateInfo* pTessDomainOriginState = nullptr;
if (reflectData.patchKind == spv::ExecutionModeTriangles) { if (reflectData.patchKind == spv::ExecutionModeTriangles) {
auto* next = (MVKVkAPIStructHeader*)pTS->pNext; for (const auto* next = (VkBaseInStructure*)pTS->pNext; next; next = next->pNext) {
while (next) {
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO: case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO:
pTessDomainOriginState = (VkPipelineTessellationDomainOriginStateCreateInfo*)next; pTessDomainOriginState = (VkPipelineTessellationDomainOriginStateCreateInfo*)next;
next = (MVKVkAPIStructHeader*)pTessDomainOriginState->pNext;
break; break;
default: default:
next = (MVKVkAPIStructHeader*)next->pNext;
break; break;
} }
} }
@ -1131,15 +1125,12 @@ void MVKGraphicsPipeline::initMVKShaderConverterContext(SPIRVToMSLConversionConf
VkPipelineTessellationDomainOriginStateCreateInfo* pTessDomainOriginState = nullptr; VkPipelineTessellationDomainOriginStateCreateInfo* pTessDomainOriginState = nullptr;
if (pCreateInfo->pTessellationState) { if (pCreateInfo->pTessellationState) {
auto* next = (MVKVkAPIStructHeader*)pCreateInfo->pTessellationState->pNext; for (const auto* next = (VkBaseInStructure*)pCreateInfo->pTessellationState->pNext; next; next = next->pNext) {
while (next) {
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO: case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO:
pTessDomainOriginState = (VkPipelineTessellationDomainOriginStateCreateInfo*)next; pTessDomainOriginState = (VkPipelineTessellationDomainOriginStateCreateInfo*)next;
next = (MVKVkAPIStructHeader*)pTessDomainOriginState->pNext;
break; break;
default: default:
next = (MVKVkAPIStructHeader*)next->pNext;
break; break;
} }
} }

View File

@ -47,9 +47,6 @@ public:
/** Binds this resource to the specified offset within the specified memory allocation. */ /** Binds this resource to the specified offset within the specified memory allocation. */
virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset); virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset);
/** Binds this resource according to the specified bind information. */
virtual VkResult bindDeviceMemory2(const void* pBindInfo);
/** Returns the device memory underlying this resource. */ /** Returns the device memory underlying this resource. */
inline MVKDeviceMemory* getDeviceMemory() { return _deviceMemory; } inline MVKDeviceMemory* getDeviceMemory() { return _deviceMemory; }
@ -88,4 +85,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;
}; };

View File

@ -21,18 +21,6 @@
#include "MVKEnvironment.h" #include "MVKEnvironment.h"
struct MVKBindDeviceMemoryInfo {
VkStructureType sType;
void* pNext;
union {
VkBuffer buffer;
VkImage image;
};
VkDeviceMemory memory;
VkDeviceSize memoryOffset;
};
#pragma mark MVKResource #pragma mark MVKResource
VkResult MVKResource::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) { VkResult MVKResource::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) {
@ -46,11 +34,6 @@ VkResult MVKResource::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize mem
return VK_SUCCESS; return VK_SUCCESS;
} }
VkResult MVKResource::bindDeviceMemory2(const void* pBindInfo) {
auto* mvkBindInfo = (const MVKBindDeviceMemoryInfo*)pBindInfo;
return bindDeviceMemory((MVKDeviceMemory*)mvkBindInfo->memory, mvkBindInfo->memoryOffset);
}
// Returns whether the specified global memory barrier requires a sync between this // Returns whether the specified global memory barrier requires a sync between this
// texture and host memory for the purpose of the host reading texture memory. // texture and host memory for the purpose of the host reading texture memory.
bool MVKResource::needsHostReadSync(VkPipelineStageFlags srcStageMask, bool MVKResource::needsHostReadSync(VkPipelineStageFlags srcStageMask,

View File

@ -39,58 +39,60 @@
#define MVK_EXTENSION_LAST(var, EXT, type) MVK_EXTENSION(var, EXT, type) #define MVK_EXTENSION_LAST(var, EXT, type) MVK_EXTENSION(var, EXT, type)
#endif #endif
MVK_EXTENSION(KHR_16bit_storage, KHR_16BIT_STORAGE, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_16bit_storage, KHR_16BIT_STORAGE, DEVICE)
MVK_EXTENSION(KHR_8bit_storage, KHR_8BIT_STORAGE, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_8bit_storage, KHR_8BIT_STORAGE, DEVICE)
MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2, DEVICE)
MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION, DEVICE)
MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, DEVICE)
MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, DEVICE)
MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, INSTANCE)
MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_external_memory, KHR_EXTERNAL_MEMORY, DEVICE)
MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(KHR_external_memory_capabilities, KHR_EXTERNAL_MEMORY_CAPABILITIES, INSTANCE)
MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, DEVICE)
MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, INSTANCE)
MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, INSTANCE)
MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, DEVICE)
MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, DEVICE)
MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, DEVICE)
MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, DEVICE)
MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE)
MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, DEVICE)
MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, DEVICE)
MVK_EXTENSION(KHR_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, DEVICE)
MVK_EXTENSION(KHR_surface, KHR_SURFACE, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, DEVICE)
MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, DEVICE)
MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_surface, KHR_SURFACE, INSTANCE)
MVK_EXTENSION(KHR_uniform_buffer_standard_layout, KHR_UNIFORM_BUFFER_STANDARD_LAYOUT, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN, DEVICE)
MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT, DEVICE)
MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, MVK_EXTENSION_DEVICE) MVK_EXTENSION(KHR_uniform_buffer_standard_layout, KHR_UNIFORM_BUFFER_STANDARD_LAYOUT, DEVICE)
MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, DEVICE)
MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, DEVICE)
MVK_EXTENSION(EXT_fragment_shader_interlock, EXT_FRAGMENT_SHADER_INTERLOCK, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, INSTANCE)
MVK_EXTENSION(EXT_hdr_metadata, EXT_HDR_METADATA, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, INSTANCE)
MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_fragment_shader_interlock, EXT_FRAGMENT_SHADER_INTERLOCK, DEVICE)
MVK_EXTENSION(EXT_inline_uniform_block, EXT_INLINE_UNIFORM_BLOCK, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_hdr_metadata, EXT_HDR_METADATA, DEVICE)
MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET, DEVICE)
MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(EXT_inline_uniform_block, EXT_INLINE_UNIFORM_BLOCK, DEVICE)
MVK_EXTENSION(EXT_post_depth_coverage, EXT_POST_DEPTH_COVERAGE, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, DEVICE)
MVK_EXTENSION(EXT_scalar_block_layout, EXT_SCALAR_BLOCK_LAYOUT, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, INSTANCE)
MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_post_depth_coverage, EXT_POST_DEPTH_COVERAGE, DEVICE)
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_scalar_block_layout, EXT_SCALAR_BLOCK_LAYOUT, DEVICE)
MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT, DEVICE)
MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER, DEVICE)
MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE, INSTANCE)
MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET, MVK_EXTENSION_DEVICE) MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT, DEVICE)
MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR, DEVICE)
MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET, DEVICE)
MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK, MVK_EXTENSION_INSTANCE) MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE, INSTANCE)
MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT, MVK_EXTENSION_DEVICE) MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE, INSTANCE)
MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT, MVK_EXTENSION_DEVICE) MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK, INSTANCE)
MVK_EXTENSION(AMD_shader_image_load_store_lod, AMD_SHADER_IMAGE_LOAD_STORE_LOD, MVK_EXTENSION_DEVICE) MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT, DEVICE)
MVK_EXTENSION(AMD_shader_trinary_minmax, AMD_SHADER_TRINARY_MINMAX, MVK_EXTENSION_DEVICE) MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT, DEVICE)
MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC, MVK_EXTENSION_DEVICE) MVK_EXTENSION(AMD_shader_image_load_store_lod, AMD_SHADER_IMAGE_LOAD_STORE_LOD, DEVICE)
MVK_EXTENSION(INTEL_shader_integer_functions2, INTEL_SHADER_INTEGER_FUNCTIONS_2, MVK_EXTENSION_DEVICE) MVK_EXTENSION(AMD_shader_trinary_minmax, AMD_SHADER_TRINARY_MINMAX, DEVICE)
MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER, MVK_EXTENSION_DEVICE) MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC, DEVICE)
MVK_EXTENSION(INTEL_shader_integer_functions2, INTEL_SHADER_INTEGER_FUNCTIONS_2, DEVICE)
MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER, DEVICE)
#undef MVK_EXTENSION #undef MVK_EXTENSION
#undef MVK_EXTENSION_LAST #undef MVK_EXTENSION_LAST

View File

@ -47,54 +47,30 @@ static VkExtensionProperties kVkExtProps_ ##EXT = mvkMakeExtProps(VK_ ##EXT ##_E
// Returns whether the specified properties are valid for this platform // Returns whether the specified properties are valid for this platform
static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
#if MVK_MACOS #if MVK_MACOS
if (pProperties == &kVkExtProps_EXT_HDR_METADATA) {
return mvkOSVersionIsAtLeast(10.15);
}
if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) {
return mvkOSVersionIsAtLeast(10.13);
}
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
return mvkOSVersionIsAtLeast(10.13);
}
if (pProperties == &kVkExtProps_EXT_POST_DEPTH_COVERAGE) { return false; }
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
return mvkOSVersionIsAtLeast(10.14);
}
if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) {
return mvkOSVersionIsAtLeast(10.13);
}
if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; } if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
if (pProperties == &kVkExtProps_AMD_SHADER_IMAGE_LOAD_STORE_LOD) { return false; }
if (pProperties == &kVkExtProps_AMD_SHADER_TRINARY_MINMAX) {
return mvkOSVersionIsAtLeast(10.14);
}
if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; } if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
if (pProperties == &kVkExtProps_EXT_POST_DEPTH_COVERAGE) { return false; }
if (pProperties == &kVkExtProps_AMD_SHADER_IMAGE_LOAD_STORE_LOD) { return false; }
if (pProperties == &kVkExtProps_EXT_HDR_METADATA) { return mvkOSVersionIsAtLeast(10.15); }
if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) { return mvkOSVersionIsAtLeast(10.13); }
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { return mvkOSVersionIsAtLeast(10.13); }
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) { return mvkOSVersionIsAtLeast(10.14); }
if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) { return mvkOSVersionIsAtLeast(10.13); }
if (pProperties == &kVkExtProps_AMD_SHADER_TRINARY_MINMAX) { return mvkOSVersionIsAtLeast(10.14); }
#endif #endif
#if MVK_IOS #if MVK_IOS
if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; } if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; }
if (pProperties == &kVkExtProps_EXT_HDR_METADATA) { return false; } if (pProperties == &kVkExtProps_EXT_HDR_METADATA) { return false; }
if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) {
return mvkOSVersionIsAtLeast(11.0); if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) { return mvkOSVersionIsAtLeast(11.0); }
} if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { return mvkOSVersionIsAtLeast(11.0); }
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { if (pProperties == &kVkExtProps_EXT_POST_DEPTH_COVERAGE) { return mvkOSVersionIsAtLeast(11.0); }
return mvkOSVersionIsAtLeast(11.0); if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) { return mvkOSVersionIsAtLeast(12.0); }
} if (pProperties == &kVkExtProps_EXT_SWAPCHAIN_COLOR_SPACE) { return mvkOSVersionIsAtLeast(9.0); }
if (pProperties == &kVkExtProps_EXT_POST_DEPTH_COVERAGE) { if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) { return mvkOSVersionIsAtLeast(11.0); }
return mvkOSVersionIsAtLeast(11.0); if (pProperties == &kVkExtProps_AMD_SHADER_TRINARY_MINMAX) { return mvkOSVersionIsAtLeast(12.0); }
}
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
return mvkOSVersionIsAtLeast(12.0);
}
if (pProperties == &kVkExtProps_EXT_SWAPCHAIN_COLOR_SPACE) {
return mvkOSVersionIsAtLeast(9.0);
}
if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) {
return mvkOSVersionIsAtLeast(11.0);
}
if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
if (pProperties == &kVkExtProps_AMD_SHADER_TRINARY_MINMAX) {
return mvkOSVersionIsAtLeast(12.0);
}
#endif #endif
return true; return true;
@ -127,17 +103,19 @@ void MVKExtensionList::initCount() {
#include "MVKExtensions.def" #include "MVKExtensions.def"
} }
#define MVK_ENSURE_EXTENSION_TYPE(var, EXT, type) vk_ ##var.enabled = vk_ ##var.enabled && MVK_EXTENSION_ ##type;
void MVKExtensionList::disableAllButEnabledInstanceExtensions() { void MVKExtensionList::disableAllButEnabledInstanceExtensions() {
#define MVK_EXTENSION_INSTANCE true #define MVK_EXTENSION_INSTANCE true
#define MVK_EXTENSION_DEVICE false #define MVK_EXTENSION_DEVICE false
#define MVK_EXTENSION(var, EXT, type) vk_ ##var.enabled = type && vk_ ##var.enabled; #define MVK_EXTENSION(var, EXT, type) MVK_ENSURE_EXTENSION_TYPE(var, EXT, type)
#include "MVKExtensions.def" #include "MVKExtensions.def"
} }
void MVKExtensionList::disableAllButEnabledDeviceExtensions() { void MVKExtensionList::disableAllButEnabledDeviceExtensions() {
#define MVK_EXTENSION_INSTANCE false #define MVK_EXTENSION_INSTANCE false
#define MVK_EXTENSION_DEVICE true #define MVK_EXTENSION_DEVICE true
#define MVK_EXTENSION(var, EXT, type) vk_ ##var.enabled = type && vk_ ##var.enabled; #define MVK_EXTENSION(var, EXT, type) MVK_ENSURE_EXTENSION_TYPE(var, EXT, type)
#include "MVKExtensions.def" #include "MVKExtensions.def"
} }

View File

@ -55,12 +55,6 @@ typedef uint16_t MVKHalfFloat;
/** A representation of the value of 1.0 as a 16-bit half-float. */ /** A representation of the value of 1.0 as a 16-bit half-float. */
#define kHalfFloat1 0x3C00 #define kHalfFloat1 0x3C00
/** Common header for many standard Vulkan API structures. */
typedef struct {
VkStructureType sType;
const void* pNext;
} MVKVkAPIStructHeader;
#pragma mark - #pragma mark -
#pragma mark Vertex content structures #pragma mark Vertex content structures

View File

@ -230,7 +230,7 @@ MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceMemoryProperties(
MVKTraceVulkanCallStart(); MVKTraceVulkanCallStart();
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice); MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
mvkPD->getPhysicalDeviceMemoryProperties(pMemoryProperties); mvkPD->getMemoryProperties(pMemoryProperties);
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
@ -2113,7 +2113,7 @@ MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceMemoryProperties2KHR(
MVKTraceVulkanCallStart(); MVKTraceVulkanCallStart();
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice); MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
mvkPD->getPhysicalDeviceMemoryProperties(pMemoryProperties); mvkPD->getMemoryProperties(pMemoryProperties);
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
@ -2664,6 +2664,21 @@ MVK_PUBLIC_SYMBOL void vkResetQueryPoolEXT(
} }
#pragma mark -
#pragma mark VK_KHR_external_memory_capabilities extension
MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceExternalBufferPropertiesKHR(
VkPhysicalDevice physicalDevice,
const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
VkExternalBufferProperties* pExternalBufferProperties) {
MVKTraceVulkanCallStart();
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
mvkPD->getExternalBufferProperties(pExternalBufferInfo, pExternalBufferProperties);
MVKTraceVulkanCallEnd();
}
#pragma mark - #pragma mark -
#pragma mark VK_EXT_metal_surface extension #pragma mark VK_EXT_metal_surface extension