metal改同步等待gpu渲染,异步和上层配合有坑。同时解决RenderTexture在metal后端随机崩溃的bug.

This commit is contained in:
u0u0
2023-07-17 14:29:16 +08:00
parent 377745b416
commit c059f1a3ae
6 changed files with 18 additions and 14 deletions

View File

@@ -637,9 +637,18 @@ void RenderTexture::end()
CCASSERT(nullptr != director, "Director is null when setting matrix stack");
Renderer *renderer = director->getRenderer();
// render may call from touch event callback, and it not in Director drawScene circle.
// need beginFrame for metal render backend, or render will crash
bool isInitFramed = renderer->isBeginFrame();
if (!isInitFramed) {
renderer->beginFrame();
}
renderer->addCommand(&_endCommand);
renderer->popGroup();
renderer->render();
if (!isInitFramed) {
renderer->endFrame();
}
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);

View File

@@ -343,10 +343,12 @@ void Renderer::render()
void Renderer::beginFrame()
{
_commandBuffer->beginFrame();
_isBeginFrame = true;
}
void Renderer::endFrame()
{
_isBeginFrame = false;
_commandBuffer->endFrame();
#ifdef CC_USE_METAL

View File

@@ -400,6 +400,10 @@ public:
/** returns whether or not a rectangle is visible or not */
bool checkVisibility(const Mat4& transform, const Size& size);
bool isBeginFrame() { return _isBeginFrame;};
void beginFrame(); /// Indicate the begining of a frame
void endFrame(); /// Finish a frame.
protected:
friend class Director;
friend class GroupCommand;
@@ -447,9 +451,6 @@ protected:
void drawMeshCommand(RenderCommand* command);
void captureScreen(RenderCommand* command);
void beginFrame(); /// Indicate the begining of a frame
void endFrame(); /// Finish a frame.
///Draw the previews queued triangles and flush previous context
void flush();
@@ -527,6 +528,7 @@ protected:
//the flag for checking whether renderer is rendering
bool _isRendering = false;
bool _isDepthTestFor2D = false;
bool _isBeginFrame = false;
GroupCommandManager* _groupCommandManager = nullptr;

View File

@@ -193,7 +193,6 @@ private:
unsigned int _renderTargetWidth = 0;
unsigned int _renderTargetHeight = 0;
dispatch_semaphore_t _frameBoundarySemaphore;
RenderPassDescriptor _prevRenderPassDescriptor;
NSAutoreleasePool* _autoReleasePool = nil;
};

View File

@@ -213,19 +213,16 @@ namespace
CommandBufferMTL::CommandBufferMTL(DeviceMTL* deviceMTL)
: _mtlCommandQueue(deviceMTL->getMTLCommandQueue())
, _frameBoundarySemaphore(dispatch_semaphore_create(MAX_INFLIGHT_BUFFER))
{
}
CommandBufferMTL::~CommandBufferMTL()
{
dispatch_semaphore_signal(_frameBoundarySemaphore);
}
void CommandBufferMTL::beginFrame()
{
_autoReleasePool = [[NSAutoreleasePool alloc] init];
dispatch_semaphore_wait(_frameBoundarySemaphore, DISPATCH_TIME_FOREVER);
_mtlCommandBuffer = [_mtlCommandQueue commandBuffer];
[_mtlCommandBuffer enqueue];
@@ -362,13 +359,8 @@ void CommandBufferMTL::endFrame()
[_mtlCommandBuffer presentDrawable:DeviceMTL::getCurrentDrawable()];
_drawableTexture = DeviceMTL::getCurrentDrawable().texture;
[_mtlCommandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBuffer) {
// GPU work is complete
// Signal the semaphore to start the CPU work
dispatch_semaphore_signal(_frameBoundarySemaphore);
}];
[_mtlCommandBuffer commit];
[_mtlCommandBuffer waitUntilCompleted];
[_mtlCommandBuffer release];
DeviceMTL::resetCurrentDrawable();
[_autoReleasePool drain];

View File

@@ -111,12 +111,12 @@ int main(int argc, char *argv[])
// create after GLView inited
ConsoleWindowController *consoleController = [[ConsoleWindowController alloc] initWithWindowNibName:@"ConsoleWindow"];
[consoleController.window orderFrontRegardless];
#endif
std::string logPath = cmd->getLogPath();
if (logPath.size() > 0) {
[consoleController openLogToFile:logPath.c_str()];
}
#endif
setupMenu();// after GLView inited