Merge pull request #1073 from cdavis5e/aliasable-dedicated-alloc
Allow multiple images for dedicated allocs of aliasabled images.
This commit is contained in:
commit
299a937887
@ -154,8 +154,9 @@ VkResult MVKDeviceMemory::addImageMemoryBinding(MVKImageMemoryBinding* mvkImg) {
|
||||
lock_guard<mutex> lock(_rezLock);
|
||||
|
||||
// If a dedicated alloc, ensure this image is the one and only image
|
||||
// I am dedicated to.
|
||||
if (_isDedicated && (_imageMemoryBindings.empty() || _imageMemoryBindings[0] != mvkImg) ) {
|
||||
// I am dedicated to. If my image is aliasable, though, allow other aliasable
|
||||
// images to bind to me.
|
||||
if (_isDedicated && (_imageMemoryBindings.empty() || !(contains(_imageMemoryBindings, mvkImg) || (_imageMemoryBindings[0]->_image->getIsAliasable() && mvkImg->_image->getIsAliasable()))) ) {
|
||||
return reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind VkImage %p to a VkDeviceMemory dedicated to resource %p. A dedicated allocation may only be used with the resource it was dedicated to.", mvkImg, getDedicatedResource() );
|
||||
}
|
||||
|
||||
|
@ -187,6 +187,9 @@ public:
|
||||
/** Returns whether this image has a linear memory layout. */
|
||||
bool getIsLinear() { return _isLinear; }
|
||||
|
||||
/** Returns whether this image is allowed to alias another image. */
|
||||
bool getIsAliasable() { return _isAliasable; }
|
||||
|
||||
/**
|
||||
* Returns the 3D extent of this image at the base mipmap level.
|
||||
* For 2D or cube images, the Z component will be 1.
|
||||
|
@ -62,6 +62,13 @@ id<MTLTexture> MVKImagePlane::getMTLTexture() {
|
||||
newTextureWithDescriptor: mtlTexDesc
|
||||
offset: memoryBinding->getDeviceMemoryOffset() + _subresources[0].layout.offset];
|
||||
if (_image->_isAliasable) { [_mtlTexture makeAliasable]; }
|
||||
} else if (_image->_isAliasable && memoryBinding->_deviceMemory->isDedicatedAllocation() &&
|
||||
!contains(memoryBinding->_deviceMemory->_imageMemoryBindings, memoryBinding)) {
|
||||
// This is a dedicated allocation, but it belongs to another aliasable image.
|
||||
// In this case, use the MTLTexture from the memory's dedicated image.
|
||||
// We know the other image must be aliasable, or I couldn't have been bound
|
||||
// to its memory: the memory object wouldn't allow it.
|
||||
_mtlTexture = [memoryBinding->_deviceMemory->_imageMemoryBindings[0]->_image->getMTLTexture(_planeIndex, mtlTexDesc.pixelFormat) retain];
|
||||
} else {
|
||||
_mtlTexture = [_image->getMTLDevice() newTextureWithDescriptor: mtlTexDesc];
|
||||
}
|
||||
@ -113,6 +120,8 @@ MTLTextureDescriptor* MVKImagePlane::newMTLTextureDescriptor() {
|
||||
}
|
||||
#endif
|
||||
|
||||
MVKImageMemoryBinding* memoryBinding = getMemoryBinding();
|
||||
|
||||
VkExtent3D extent = _image->getExtent3D(_planeIndex, 0);
|
||||
MTLTextureDescriptor* mtlTexDesc = [MTLTextureDescriptor new]; // retained
|
||||
mtlTexDesc.pixelFormat = mtlPixFmt;
|
||||
@ -123,7 +132,12 @@ MTLTextureDescriptor* MVKImagePlane::newMTLTextureDescriptor() {
|
||||
mtlTexDesc.mipmapLevelCount = _image->_mipLevels;
|
||||
mtlTexDesc.sampleCount = mvkSampleCountFromVkSampleCountFlagBits(_image->_samples);
|
||||
mtlTexDesc.arrayLength = _image->_arrayLayers;
|
||||
mtlTexDesc.usageMVK = _image->getPixelFormats()->getMTLTextureUsage(_image->_usage, mtlPixFmt, minUsage, _image->_isLinear, _image->_hasMutableFormat, _image->_hasExtendedUsage);
|
||||
if (_image->_isAliasable && memoryBinding->_deviceMemory && memoryBinding->_deviceMemory->isDedicatedAllocation()) {
|
||||
// Unfortunately, in this instance, we must presume the texture can be used for anything.
|
||||
mtlTexDesc.usageMVK = MTLTextureUsageUnknown;
|
||||
} else {
|
||||
mtlTexDesc.usageMVK = _image->getPixelFormats()->getMTLTextureUsage(_image->_usage, mtlPixFmt, minUsage, _image->_isLinear, _image->_hasMutableFormat, _image->_hasExtendedUsage);
|
||||
}
|
||||
mtlTexDesc.storageModeMVK = _image->getMTLStorageMode();
|
||||
mtlTexDesc.cpuCacheMode = _image->getMTLCPUCacheMode();
|
||||
|
||||
@ -831,6 +845,7 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
||||
MVKPixelFormats* pixFmts = getPixelFormats();
|
||||
_vkFormat = pCreateInfo->format;
|
||||
_usage = pCreateInfo->usage;
|
||||
_isAliasable = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_ALIAS_BIT);
|
||||
_hasMutableFormat = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
|
||||
_hasExtendedUsage = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_EXTENDED_USAGE_BIT);
|
||||
|
||||
@ -876,7 +891,6 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
||||
[mtlTexDesc release];
|
||||
memoryBinding->_byteCount += sizeAndAlign.size;
|
||||
memoryBinding->_byteAlignment = std::max(memoryBinding->_byteAlignment, (VkDeviceSize)sizeAndAlign.align);
|
||||
_isAliasable = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_ALIAS_BIT);
|
||||
} else if (_isLinearForAtomics && _device->_pMetalFeatures->placementHeaps) {
|
||||
NSUInteger bufferLength = 0;
|
||||
for (uint32_t mipLvl = 0; mipLvl < _mipLevels; mipLvl++) {
|
||||
@ -886,7 +900,6 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
||||
MTLSizeAndAlign sizeAndAlign = [_device->getMTLDevice() heapBufferSizeAndAlignWithLength: bufferLength options: MTLResourceStorageModePrivate];
|
||||
memoryBinding->_byteCount += sizeAndAlign.size;
|
||||
memoryBinding->_byteAlignment = std::max(std::max(memoryBinding->_byteAlignment, _rowByteAlignment), (VkDeviceSize)sizeAndAlign.align);
|
||||
_isAliasable = mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_ALIAS_BIT);
|
||||
} else {
|
||||
for (uint32_t mipLvl = 0; mipLvl < _mipLevels; mipLvl++) {
|
||||
VkExtent3D mipExtent = getExtent3D(planeIndex, mipLvl);
|
||||
|
@ -470,7 +470,7 @@ void mvkReleaseContainerContents(C& container) {
|
||||
|
||||
/** Returns whether the container contains an item equal to the value. */
|
||||
template<class C, class T>
|
||||
bool contains(const C& container, const T& val) {
|
||||
bool contains(C& container, const T& val) {
|
||||
for (const T& cVal : container) { if (cVal == val) { return true; } }
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user