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