Fix memory leak when pre-filling MTLCommandBuffers.
Wrap MVKCommandBuffer::prefill() in autoreleasepool. For non-reusable MVKCommandBuffers, release command instances once prefilling is done to reduce memory pressure.
This commit is contained in:
parent
30658f05f5
commit
7658bccfba
@ -17,16 +17,15 @@ For best results, use a Markdown reader.*
|
||||
MoltenVK 1.0.41
|
||||
---------------
|
||||
|
||||
Released TBD
|
||||
Released 2020/03/30
|
||||
|
||||
- Fix issue where immutable samplers are removed during descriptor update.
|
||||
- Guard against Metal validation assertion from reuse of query number
|
||||
within a single `MTLRenderEncoder`.
|
||||
- Guard against Metal validation assertion from reuse of query number within a single `MTLRenderEncoder`.
|
||||
- Increase value of `VkPhysicalDeviceLimits::minStorageBufferOffsetAlignment`
|
||||
to `16` to avoid Metal validation assertions.
|
||||
- Add ability to disable command memory pooling using `MVK_CONFIG_USE_COMMAND_POOLING`
|
||||
environment variable.
|
||||
|
||||
- Fix memory leak when pre-filling `MTLCommandBuffers` using `MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS`.
|
||||
|
||||
|
||||
|
||||
|
@ -152,6 +152,7 @@ protected:
|
||||
bool canPrefill();
|
||||
void prefill();
|
||||
void clearPrefilledMTLCommandBuffer();
|
||||
void releaseCommands();
|
||||
|
||||
MVKCommand* _head = nullptr;
|
||||
MVKCommand* _tail = nullptr;
|
||||
|
@ -54,18 +54,20 @@ VkResult MVKCommandBuffer::begin(const VkCommandBufferBeginInfo* pBeginInfo) {
|
||||
return getConfigurationResult();
|
||||
}
|
||||
|
||||
VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
|
||||
void MVKCommandBuffer::releaseCommands() {
|
||||
MVKCommand* cmd = _head;
|
||||
while (cmd) {
|
||||
MVKCommand* nextCmd = cmd->_next; // Establish next before returning current to pool.
|
||||
cmd->returnToPool();
|
||||
cmd = nextCmd;
|
||||
}
|
||||
|
||||
clearPrefilledMTLCommandBuffer();
|
||||
|
||||
_head = nullptr;
|
||||
_tail = nullptr;
|
||||
}
|
||||
|
||||
VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
|
||||
clearPrefilledMTLCommandBuffer();
|
||||
releaseCommands();
|
||||
_doesContinueRenderPass = false;
|
||||
_canAcceptCommands = false;
|
||||
_isReusable = false;
|
||||
@ -140,18 +142,24 @@ bool MVKCommandBuffer::canExecute() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we can, prefill a MTLCommandBuffer with the commands in this command buffer
|
||||
// If we can, prefill a MTLCommandBuffer with the commands in this command buffer.
|
||||
// Wrap in autorelease pool to capture autoreleased Metal encoding activity.
|
||||
void MVKCommandBuffer::prefill() {
|
||||
@autoreleasepool {
|
||||
clearPrefilledMTLCommandBuffer();
|
||||
|
||||
clearPrefilledMTLCommandBuffer();
|
||||
if ( !canPrefill() ) { return; }
|
||||
|
||||
if ( !canPrefill() ) { return; }
|
||||
uint32_t qIdx = 0;
|
||||
_prefilledMTLCmdBuffer = _commandPool->newMTLCommandBuffer(qIdx); // retain
|
||||
|
||||
uint32_t qIdx = 0;
|
||||
_prefilledMTLCmdBuffer = _commandPool->newMTLCommandBuffer(qIdx); // retain
|
||||
MVKCommandEncoder encoder(this);
|
||||
encoder.encode(_prefilledMTLCmdBuffer);
|
||||
|
||||
MVKCommandEncoder encoder(this);
|
||||
encoder.encode(_prefilledMTLCmdBuffer);
|
||||
// Once encoded onto Metal, if this command buffer is not reusable, we don't need the
|
||||
// MVKCommand instances anymore, so release them in order to reduce memory pressure.
|
||||
if ( !_isReusable ) { releaseCommands(); }
|
||||
}
|
||||
}
|
||||
|
||||
bool MVKCommandBuffer::canPrefill() {
|
||||
|
@ -249,7 +249,7 @@ void MVKQueueCommandBufferSubmission::setActiveMTLCommandBuffer(id<MTLCommandBuf
|
||||
|
||||
if (_activeMTLCommandBuffer) { commitActiveMTLCommandBuffer(); }
|
||||
|
||||
_activeMTLCommandBuffer = mtlCmdBuff; // not retained
|
||||
_activeMTLCommandBuffer = [mtlCmdBuff retain]; // retained to handle prefilled
|
||||
[_activeMTLCommandBuffer enqueue];
|
||||
}
|
||||
|
||||
@ -276,8 +276,9 @@ void MVKQueueCommandBufferSubmission::commitActiveMTLCommandBuffer(bool signalCo
|
||||
|
||||
// Use temp var because callback may destroy this instance before this function ends.
|
||||
id<MTLCommandBuffer> mtlCmdBuff = _activeMTLCommandBuffer;
|
||||
_activeMTLCommandBuffer = nil; // not retained
|
||||
_activeMTLCommandBuffer = nil;
|
||||
[mtlCmdBuff commit];
|
||||
[mtlCmdBuff release]; // retained
|
||||
}
|
||||
|
||||
void MVKQueueCommandBufferSubmission::finish() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user