Merge pull request #1382 from billhollings/coherent-texture-flushing
Reorganize coherent texture flushing on memory map and unmap.
This commit is contained in:
commit
c2ded942e2
@ -88,8 +88,6 @@ void MVKCmdCopyImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
|
||||
VkBufferImageCopy vkDstCopies[copyCnt];
|
||||
size_t tmpBuffSize = 0;
|
||||
|
||||
_srcImage->flushToDevice(0, VK_WHOLE_SIZE);
|
||||
|
||||
for (uint32_t copyIdx = 0; copyIdx < copyCnt; copyIdx++) {
|
||||
auto& vkIC = _vkImageCopies[copyIdx];
|
||||
|
||||
|
@ -3616,7 +3616,7 @@ VkResult MVKDevice::invalidateMappedMemoryRanges(uint32_t memRangeCount, const V
|
||||
for (uint32_t i = 0; i < memRangeCount; i++) {
|
||||
const VkMappedMemoryRange* pMem = &pMemRanges[i];
|
||||
MVKDeviceMemory* mvkMem = (MVKDeviceMemory*)pMem->memory;
|
||||
VkResult r = mvkMem->pullFromDevice(pMem->offset, pMem->size, false, &mvkBlitEnc);
|
||||
VkResult r = mvkMem->pullFromDevice(pMem->offset, pMem->size, &mvkBlitEnc);
|
||||
if (rslt == VK_SUCCESS) { rslt = r; }
|
||||
}
|
||||
if (mvkBlitEnc.mtlBlitEncoder) { [mvkBlitEnc.mtlBlitEncoder endEncoding]; }
|
||||
|
@ -93,17 +93,11 @@ public:
|
||||
/** Returns whether this device memory is currently mapped to host memory. */
|
||||
bool isMapped() { return _mappedRange.size > 0; }
|
||||
|
||||
/**
|
||||
* If this memory is host-visible, the specified memory range is flushed to the device.
|
||||
* Normally, flushing will only occur if the device memory is non-coherent, but flushing
|
||||
* to coherent memory can be forced by setting evenIfCoherent to true.
|
||||
*/
|
||||
VkResult flushToDevice(VkDeviceSize offset, VkDeviceSize size, bool evenIfCoherent = false);
|
||||
/** If this memory is host-visible, the specified memory range is flushed to the device. */
|
||||
VkResult flushToDevice(VkDeviceSize offset, VkDeviceSize size);
|
||||
|
||||
/**
|
||||
* If this memory is host-visible, pulls the specified memory range from the device.
|
||||
* Normally, pulling will only occur if the device memory is non-coherent, but pulling
|
||||
* to coherent memory can be forced by setting evenIfCoherent to true.
|
||||
*
|
||||
* If pBlitEnc is not null, it points to a holder for a MTLBlitCommandEncoder and its
|
||||
* associated MTLCommandBuffer. If this instance has a MTLBuffer using managed memory,
|
||||
@ -114,7 +108,6 @@ public:
|
||||
*/
|
||||
VkResult pullFromDevice(VkDeviceSize offset,
|
||||
VkDeviceSize size,
|
||||
bool evenIfCoherent = false,
|
||||
MVKMTLBlitEncoder* pBlitEnc = nullptr);
|
||||
|
||||
|
||||
@ -172,8 +165,10 @@ protected:
|
||||
id<MTLHeap> _mtlHeap = nil;
|
||||
void* _pMemory = nullptr;
|
||||
void* _pHostMemory = nullptr;
|
||||
bool _isDedicated = false;
|
||||
VkMemoryPropertyFlags _vkMemProps;
|
||||
MTLStorageMode _mtlStorageMode;
|
||||
MTLCPUCacheMode _mtlCPUCacheMode;
|
||||
bool _isDedicated = false;
|
||||
|
||||
};
|
||||
|
||||
|
@ -55,8 +55,11 @@ VkResult MVKDeviceMemory::map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMa
|
||||
|
||||
*ppData = (void*)((uintptr_t)_pMemory + offset);
|
||||
|
||||
// Coherent memory does not require flushing by app, so we must flush now, to handle any texture updates.
|
||||
pullFromDevice(offset, size, isMemoryHostCoherent());
|
||||
// Coherent memory does not require flushing by app, so we must flush now
|
||||
// to support Metal textures that actually reside in non-coherent memory.
|
||||
if (mvkIsAnyFlagEnabled(_vkMemProps, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
|
||||
pullFromDevice(offset, size);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
@ -68,54 +71,57 @@ void MVKDeviceMemory::unmap() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Coherent memory does not require flushing by app, so we must flush now.
|
||||
flushToDevice(_mappedRange.offset, _mappedRange.size, isMemoryHostCoherent());
|
||||
// Coherent memory does not require flushing by app, so we must flush now
|
||||
// to support Metal textures that actually reside in non-coherent memory.
|
||||
if (mvkIsAnyFlagEnabled(_vkMemProps, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
|
||||
flushToDevice(_mappedRange.offset, _mappedRange.size);
|
||||
}
|
||||
|
||||
_mappedRange.offset = 0;
|
||||
_mappedRange.size = 0;
|
||||
}
|
||||
|
||||
VkResult MVKDeviceMemory::flushToDevice(VkDeviceSize offset, VkDeviceSize size, bool evenIfCoherent) {
|
||||
// Coherent memory is flushed on unmap(), so it is only flushed if forced
|
||||
VkResult MVKDeviceMemory::flushToDevice(VkDeviceSize offset, VkDeviceSize size) {
|
||||
VkDeviceSize memSize = adjustMemorySize(size, offset);
|
||||
if (memSize > 0 && isMemoryHostAccessible() && (evenIfCoherent || !isMemoryHostCoherent()) ) {
|
||||
if (memSize == 0 || !isMemoryHostAccessible()) { return VK_SUCCESS; }
|
||||
|
||||
#if MVK_MACOS
|
||||
if (_mtlBuffer && _mtlStorageMode == MTLStorageModeManaged) {
|
||||
[_mtlBuffer didModifyRange: NSMakeRange(offset, memSize)];
|
||||
}
|
||||
if (_mtlBuffer && _mtlStorageMode == MTLStorageModeManaged) {
|
||||
[_mtlBuffer didModifyRange: NSMakeRange(offset, memSize)];
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we have an MTLHeap object, there's no need to sync memory manually between images and the buffer.
|
||||
if (!_mtlHeap) {
|
||||
lock_guard<mutex> lock(_rezLock);
|
||||
for (auto& img : _imageMemoryBindings) { img->flushToDevice(offset, memSize); }
|
||||
for (auto& buf : _buffers) { buf->flushToDevice(offset, memSize); }
|
||||
}
|
||||
// If we have an MTLHeap object, there's no need to sync memory manually between resources and the buffer.
|
||||
if ( !_mtlHeap ) {
|
||||
lock_guard<mutex> lock(_rezLock);
|
||||
for (auto& img : _imageMemoryBindings) { img->flushToDevice(offset, memSize); }
|
||||
for (auto& buf : _buffers) { buf->flushToDevice(offset, memSize); }
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult MVKDeviceMemory::pullFromDevice(VkDeviceSize offset,
|
||||
VkDeviceSize size,
|
||||
bool evenIfCoherent,
|
||||
MVKMTLBlitEncoder* pBlitEnc) {
|
||||
// Coherent memory is flushed on unmap(), so it is only flushed if forced
|
||||
VkDeviceSize memSize = adjustMemorySize(size, offset);
|
||||
if (memSize > 0 && isMemoryHostAccessible() && (evenIfCoherent || !isMemoryHostCoherent()) && !_mtlHeap) {
|
||||
if (memSize == 0 || !isMemoryHostAccessible()) { return VK_SUCCESS; }
|
||||
|
||||
#if MVK_MACOS
|
||||
if (pBlitEnc && _mtlBuffer && _mtlStorageMode == MTLStorageModeManaged) {
|
||||
if ( !pBlitEnc->mtlCmdBuffer) { pBlitEnc->mtlCmdBuffer = _device->getAnyQueue()->getMTLCommandBuffer(kMVKCommandUseInvalidateMappedMemoryRanges); }
|
||||
if ( !pBlitEnc->mtlBlitEncoder) { pBlitEnc->mtlBlitEncoder = [pBlitEnc->mtlCmdBuffer blitCommandEncoder]; }
|
||||
[pBlitEnc->mtlBlitEncoder synchronizeResource: _mtlBuffer];
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we have an MTLHeap object, there's no need to sync memory manually between resources and the buffer.
|
||||
if ( !_mtlHeap ) {
|
||||
lock_guard<mutex> lock(_rezLock);
|
||||
for (auto& img : _imageMemoryBindings) { img->pullFromDevice(offset, memSize); }
|
||||
for (auto& buf : _buffers) { buf->pullFromDevice(offset, memSize); }
|
||||
|
||||
#if MVK_MACOS
|
||||
if (pBlitEnc && _mtlBuffer && _mtlStorageMode == MTLStorageModeManaged) {
|
||||
if ( !pBlitEnc->mtlCmdBuffer) { pBlitEnc->mtlCmdBuffer = _device->getAnyQueue()->getMTLCommandBuffer(kMVKCommandUseInvalidateMappedMemoryRanges); }
|
||||
if ( !pBlitEnc->mtlBlitEncoder) { pBlitEnc->mtlBlitEncoder = [pBlitEnc->mtlCmdBuffer blitCommandEncoder]; }
|
||||
[pBlitEnc->mtlBlitEncoder synchronizeResource: _mtlBuffer];
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
@ -271,9 +277,9 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
||||
const VkMemoryAllocateInfo* pAllocateInfo,
|
||||
const VkAllocationCallbacks* pAllocator) : MVKVulkanAPIDeviceObject(device) {
|
||||
// Set Metal memory parameters
|
||||
VkMemoryPropertyFlags vkMemProps = _device->_pMemoryProperties->memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags;
|
||||
_mtlStorageMode = mvkMTLStorageModeFromVkMemoryPropertyFlags(vkMemProps);
|
||||
_mtlCPUCacheMode = mvkMTLCPUCacheModeFromVkMemoryPropertyFlags(vkMemProps);
|
||||
_vkMemProps = _device->_pMemoryProperties->memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags;
|
||||
_mtlStorageMode = mvkMTLStorageModeFromVkMemoryPropertyFlags(_vkMemProps);
|
||||
_mtlCPUCacheMode = mvkMTLCPUCacheModeFromVkMemoryPropertyFlags(_vkMemProps);
|
||||
|
||||
_allocationSize = pAllocateInfo->allocationSize;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user