fix!: (windows) add flushAndWait call to capture() to prevent stalling on Windows; use provided buffer as pixelBuffer rather than duplicate allocation

This commit is contained in:
Nick Fisher
2024-10-23 15:02:28 +11:00
parent e2175db7cb
commit cda4027f83

View File

@@ -1076,23 +1076,13 @@ namespace thermion
void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, void (*onComplete)()) void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, void (*onComplete)())
{ {
if (!swapChain)
{
Log("NO SWAPCHAIN");
return;
}
Viewport const &vp = view->getViewport(); Viewport const &vp = view->getViewport();
size_t pixelBufferSize = vp.width * vp.height * 4; size_t pixelBufferSize = vp.width * vp.height * 4;
auto *pixelBuffer = new uint8_t[pixelBufferSize];
auto callback = [](void *buf, size_t size, void *data) auto callback = [](void *buf, size_t size, void *data)
{ {
auto frameCallbackData = (std::vector<void *> *)data; auto frameCallbackData = (std::vector<void *> *)data;
uint8_t *out = (uint8_t *)(frameCallbackData->at(0));
void *callbackPtr = frameCallbackData->at(1); void *callbackPtr = frameCallbackData->at(1);
memcpy(out, buf, size);
delete frameCallbackData; delete frameCallbackData;
if (callbackPtr) if (callbackPtr)
{ {
@@ -1113,7 +1103,7 @@ namespace thermion
auto dispatcher = new CaptureCallbackHandler(); auto dispatcher = new CaptureCallbackHandler();
auto pbd = Texture::PixelBufferDescriptor( auto pbd = Texture::PixelBufferDescriptor(
pixelBuffer, pixelBufferSize, out, pixelBufferSize,
Texture::Format::RGBA, Texture::Format::RGBA,
Texture::Type::UBYTE, dispatcher, callback, userData); Texture::Type::UBYTE, dispatcher, callback, userData);
_renderer->beginFrame(swapChain, 0); _renderer->beginFrame(swapChain, 0);
@@ -1124,6 +1114,8 @@ namespace thermion
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
_engine->execute(); _engine->execute();
emscripten_webgl_commit_frame(); emscripten_webgl_commit_frame();
#else
_engine->flushAndWait();
#endif #endif
if (fence) if (fence)
{ {
@@ -1134,11 +1126,6 @@ namespace thermion
void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, RenderTarget *renderTarget, void (*onComplete)()) void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, RenderTarget *renderTarget, void (*onComplete)())
{ {
if (!(renderTarget || swapChain)) {
Log("NO RENDER TARGET OR SWAPCHAIN");
return;
}
if(swapChain && !_engine->isValid(swapChain)) { if(swapChain && !_engine->isValid(swapChain)) {
Log("SWAPCHAIN PROVIDED BUT NOT VALID"); Log("SWAPCHAIN PROVIDED BUT NOT VALID");
return; return;
@@ -1154,14 +1141,11 @@ namespace thermion
Viewport const &vp = view->getViewport(); Viewport const &vp = view->getViewport();
size_t pixelBufferSize = vp.width * vp.height * 4; size_t pixelBufferSize = vp.width * vp.height * 4;
auto *pixelBuffer = new uint8_t[pixelBufferSize];
auto callback = [](void *buf, size_t size, void *data) auto callback = [](void *buf, size_t size, void *data)
{ {
auto frameCallbackData = (std::vector<void *> *)data; auto frameCallbackData = (std::vector<void *> *)data;
uint8_t *out = (uint8_t *)(frameCallbackData->at(0));
void *callbackPtr = frameCallbackData->at(1); void *callbackPtr = frameCallbackData->at(1);
memcpy(out, buf, size);
delete frameCallbackData; delete frameCallbackData;
if (callbackPtr) if (callbackPtr)
{ {
@@ -1182,7 +1166,7 @@ namespace thermion
auto dispatcher = new CaptureCallbackHandler(); auto dispatcher = new CaptureCallbackHandler();
auto pbd = Texture::PixelBufferDescriptor( auto pbd = Texture::PixelBufferDescriptor(
pixelBuffer, pixelBufferSize, out, pixelBufferSize,
Texture::Format::RGBA, Texture::Format::RGBA,
Texture::Type::UBYTE, dispatcher, callback, userData); Texture::Type::UBYTE, dispatcher, callback, userData);
_renderer->beginFrame(swapChain, 0); _renderer->beginFrame(swapChain, 0);
@@ -1193,6 +1177,8 @@ namespace thermion
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
_engine->execute(); _engine->execute();
emscripten_webgl_commit_frame(); emscripten_webgl_commit_frame();
#else
_engine->flushAndWait();
#endif #endif
if (fence) if (fence)
{ {