Merge pull request #1561 from BeastLe9enD/master
Added optimized support for VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT when MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS is used
This commit is contained in:
commit
76aca81fac
@ -166,7 +166,9 @@ protected:
|
||||
bool canPrefill();
|
||||
void prefill();
|
||||
void clearPrefilledMTLCommandBuffer();
|
||||
void releaseCommands();
|
||||
void releaseCommands(MVKCommand* command);
|
||||
void releaseRecordedCommands();
|
||||
void flushImmediateCmdEncoder();
|
||||
|
||||
MVKCommand* _head = nullptr;
|
||||
MVKCommand* _tail = nullptr;
|
||||
@ -175,6 +177,8 @@ protected:
|
||||
std::atomic_flag _isExecutingNonConcurrently;
|
||||
VkCommandBufferInheritanceInfo _secondaryInheritanceInfo;
|
||||
id<MTLCommandBuffer> _prefilledMTLCmdBuffer = nil;
|
||||
MVKCommandEncodingContext* _immediateCmdEncodingContext = nullptr;
|
||||
MVKCommandEncoder* _immediateCmdEncoder = nullptr;
|
||||
bool _isSecondary;
|
||||
bool _doesContinueRenderPass;
|
||||
bool _canAcceptCommands;
|
||||
@ -275,6 +279,10 @@ public:
|
||||
/** Encode commands from the command buffer onto the Metal command buffer. */
|
||||
void encode(id<MTLCommandBuffer> mtlCmdBuff, MVKCommandEncodingContext* pEncodingContext);
|
||||
|
||||
void beginEncoding(id<MTLCommandBuffer> mtlCmdBuff, MVKCommandEncodingContext* pEncodingContext);
|
||||
void encodeCommands(MVKCommand* command);
|
||||
void endEncoding();
|
||||
|
||||
/** Encode commands from the specified secondary command buffer onto the Metal command buffer. */
|
||||
void encodeSecondary(MVKCommandBuffer* secondaryCmdBuffer);
|
||||
|
||||
|
@ -51,23 +51,50 @@ VkResult MVKCommandBuffer::begin(const VkCommandBufferBeginInfo* pBeginInfo) {
|
||||
bool hasInheritInfo = mvkSetOrClear(&_secondaryInheritanceInfo, pInheritInfo);
|
||||
_doesContinueRenderPass = mvkAreAllFlagsEnabled(usage, VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) && hasInheritInfo;
|
||||
|
||||
if(canPrefill()) {
|
||||
@autoreleasepool {
|
||||
uint32_t qIdx = 0;
|
||||
_prefilledMTLCmdBuffer = _commandPool->newMTLCommandBuffer(qIdx); // retain
|
||||
|
||||
_immediateCmdEncodingContext = new MVKCommandEncodingContext;
|
||||
|
||||
_immediateCmdEncoder = new MVKCommandEncoder(this);
|
||||
_immediateCmdEncoder->beginEncoding(_prefilledMTLCmdBuffer, _immediateCmdEncodingContext);
|
||||
}
|
||||
}
|
||||
|
||||
return getConfigurationResult();
|
||||
}
|
||||
|
||||
void MVKCommandBuffer::releaseCommands() {
|
||||
MVKCommand* cmd = _head;
|
||||
while (cmd) {
|
||||
MVKCommand* nextCmd = cmd->_next; // Establish next before returning current to pool.
|
||||
(cmd->getTypePool(getCommandPool()))->returnObject(cmd);
|
||||
cmd = nextCmd;
|
||||
void MVKCommandBuffer::releaseCommands(MVKCommand* command) {
|
||||
while(command) {
|
||||
MVKCommand* nextCommand = command->_next; // Establish next before returning current to pool.
|
||||
(command->getTypePool(getCommandPool()))->returnObject(command);
|
||||
command = nextCommand;
|
||||
}
|
||||
}
|
||||
|
||||
void MVKCommandBuffer::releaseRecordedCommands() {
|
||||
releaseCommands(_head);
|
||||
_head = nullptr;
|
||||
_tail = nullptr;
|
||||
}
|
||||
|
||||
void MVKCommandBuffer::flushImmediateCmdEncoder() {
|
||||
if(_immediateCmdEncoder) {
|
||||
_immediateCmdEncoder->endEncoding();
|
||||
delete _immediateCmdEncoder;
|
||||
_immediateCmdEncoder = nullptr;
|
||||
|
||||
delete _immediateCmdEncodingContext;
|
||||
_immediateCmdEncodingContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
|
||||
flushImmediateCmdEncoder();
|
||||
clearPrefilledMTLCommandBuffer();
|
||||
releaseCommands();
|
||||
releaseRecordedCommands();
|
||||
_doesContinueRenderPass = false;
|
||||
_canAcceptCommands = false;
|
||||
_isReusable = false;
|
||||
@ -89,7 +116,9 @@ VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
|
||||
|
||||
VkResult MVKCommandBuffer::end() {
|
||||
_canAcceptCommands = false;
|
||||
prefill();
|
||||
|
||||
flushImmediateCmdEncoder();
|
||||
|
||||
return getConfigurationResult();
|
||||
}
|
||||
|
||||
@ -99,6 +128,15 @@ void MVKCommandBuffer::addCommand(MVKCommand* command) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(_immediateCmdEncoder) {
|
||||
_immediateCmdEncoder->encodeCommands(command);
|
||||
|
||||
if( !_isReusable ) {
|
||||
releaseCommands(command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_tail) { _tail->_next = command; }
|
||||
command->_next = nullptr;
|
||||
_tail = command;
|
||||
@ -141,27 +179,6 @@ bool MVKCommandBuffer::canExecute() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
if ( !canPrefill() ) { return; }
|
||||
|
||||
uint32_t qIdx = 0;
|
||||
_prefilledMTLCmdBuffer = _commandPool->newMTLCommandBuffer(qIdx); // retain
|
||||
|
||||
MVKCommandEncodingContext encodingContext;
|
||||
MVKCommandEncoder encoder(this);
|
||||
encoder.encode(_prefilledMTLCmdBuffer, &encodingContext);
|
||||
|
||||
// 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() {
|
||||
bool wantPrefill = _device->shouldPrefillMTLCommandBuffers();
|
||||
return wantPrefill && !(_isSecondary || _supportsConcurrentExecution);
|
||||
@ -251,6 +268,12 @@ MVKRenderSubpass* MVKCommandBuffer::getLastMultiviewSubpass() {
|
||||
|
||||
void MVKCommandEncoder::encode(id<MTLCommandBuffer> mtlCmdBuff,
|
||||
MVKCommandEncodingContext* pEncodingContext) {
|
||||
beginEncoding(mtlCmdBuff, pEncodingContext);
|
||||
encodeCommands(_cmdBuffer->_head);
|
||||
endEncoding();
|
||||
}
|
||||
|
||||
void MVKCommandEncoder::beginEncoding(id<MTLCommandBuffer> mtlCmdBuff, MVKCommandEncodingContext* pEncodingContext) {
|
||||
_framebuffer = nullptr;
|
||||
_renderPass = nullptr;
|
||||
_subpassContents = VK_SUBPASS_CONTENTS_INLINE;
|
||||
@ -262,20 +285,25 @@ void MVKCommandEncoder::encode(id<MTLCommandBuffer> mtlCmdBuff,
|
||||
_mtlCmdBuffer = mtlCmdBuff; // not retained
|
||||
|
||||
setLabelIfNotNil(_mtlCmdBuffer, _cmdBuffer->_debugName);
|
||||
}
|
||||
|
||||
MVKCommand* cmd = _cmdBuffer->_head;
|
||||
while (cmd) {
|
||||
void MVKCommandEncoder::encodeCommands(MVKCommand* command) {
|
||||
while(command) {
|
||||
uint32_t prevMVPassIdx = _multiviewPassIndex;
|
||||
cmd->encode(this);
|
||||
command->encode(this);
|
||||
|
||||
if(_multiviewPassIndex > prevMVPassIdx) {
|
||||
// This means we're in a multiview render pass, and we moved on to the
|
||||
// next view group. Re-encode all commands in the subpass again for this group.
|
||||
cmd = _lastMultiviewPassCmd->_next;
|
||||
|
||||
command = _lastMultiviewPassCmd->_next;
|
||||
} else {
|
||||
cmd = cmd->_next;
|
||||
command = command->_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MVKCommandEncoder::endEncoding() {
|
||||
endCurrentMetalEncoding();
|
||||
finishQueries();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user