core: Fix Vulkan snapshot timing for headless too (#4397)

Co-authored-by: Adrian Cojocaru <adrian.cojocaru92@yahoo.com>
This commit is contained in:
Taku Fukada
2026-07-14 02:04:18 +09:00
committed by GitHub
parent 945ffff229
commit 764accc8f5
3 changed files with 28 additions and 42 deletions

View File

@@ -38,8 +38,6 @@ private:
private:
std::unique_ptr<Impl> impl;
bool active = false;
std::unique_ptr<Texture2D> texture;
};
} // namespace vulkan

View File

@@ -26,8 +26,8 @@ public:
void bind() override {}
void swap() override {
queueSurfaceRead();
SurfaceRenderableResource::swap();
static_cast<Context&>(backend.getContext()).waitFrame();
}
};
@@ -42,8 +42,6 @@ HeadlessBackend::HeadlessBackend(const Size size_,
HeadlessBackend::~HeadlessBackend() {
gfx::BackendScope guard{*this, gfx::BackendScope::ScopeType::Implicit};
texture.reset();
// Explicitly reset the renderable resource
resource.reset();
// Explicitly reset the context so that it is destructed and cleaned up
@@ -79,21 +77,11 @@ PremultipliedImage HeadlessBackend::readStillImage() {
resource = std::make_unique<HeadlessRenderableResource>(*this);
}
auto& contextImpl = static_cast<Context&>(*context);
auto& resourceImpl = static_cast<HeadlessRenderableResource&>(*resource);
if (!texture) {
texture = std::make_unique<Texture2D>(contextImpl);
texture->setFormat(gfx::TexturePixelType::RGBA, gfx::TextureChannelDataType::UnsignedByte);
texture->setUsage(Texture2DUsage::Read);
}
texture->setSize(size);
contextImpl.waitFrame();
texture->copyImage(resourceImpl.getAcquiredImage(), size);
return std::move(*texture->readImage());
auto image = resourceImpl.readImage();
assert(image);
return std::move(*image);
}
RendererBackend* HeadlessBackend::getRendererBackend() {

View File

@@ -483,7 +483,9 @@ void SurfaceRenderableResource::queueSurfaceRead() {
}
surfaceRead = true;
backend.getContext<Context>().requestSurfaceUpdate(false);
if (surface) {
backend.getContext<Context>().requestSurfaceUpdate(false);
}
}
void SurfaceRenderableResource::copySurfaceToReadTexture() {
@@ -502,25 +504,23 @@ void SurfaceRenderableResource::copySurfaceToReadTexture() {
const auto swapchainImage = getAcquiredImage();
auto& commandBuffer = contextImpl.getCommandBuffer();
if (surface) {
const auto barrier = vk::ImageMemoryBarrier()
const auto oldLayout = surface ? vk::ImageLayout::ePresentSrcKHR : vk::ImageLayout::eTransferSrcOptimal;
const auto srcStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
const vk::AccessFlags srcAccess = vk::AccessFlagBits::eColorAttachmentWrite;
const vk::AccessFlags dstAccess = vk::AccessFlagBits::eTransferRead;
const auto readBarrier = vk::ImageMemoryBarrier()
.setImage(swapchainImage)
.setOldLayout(vk::ImageLayout::ePresentSrcKHR)
.setOldLayout(oldLayout)
.setNewLayout(vk::ImageLayout::eTransferSrcOptimal)
.setSrcAccessMask({})
.setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
.setSrcAccessMask(srcAccess)
.setDstAccessMask(dstAccess)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
commandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eTransfer,
{},
nullptr,
nullptr,
barrier,
dispatcher);
}
commandBuffer->pipelineBarrier(
srcStage, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, readBarrier, dispatcher);
bool useBlit =
surface &&
@@ -536,22 +536,22 @@ void SurfaceRenderableResource::copySurfaceToReadTexture() {
}
if (surface) {
const auto barrier = vk::ImageMemoryBarrier()
.setImage(swapchainImage)
.setOldLayout(vk::ImageLayout::eTransferSrcOptimal)
.setNewLayout(vk::ImageLayout::ePresentSrcKHR)
.setSrcAccessMask(vk::AccessFlagBits::eMemoryRead)
.setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
const auto presentBarrier = vk::ImageMemoryBarrier()
.setImage(swapchainImage)
.setOldLayout(vk::ImageLayout::eTransferSrcOptimal)
.setNewLayout(vk::ImageLayout::ePresentSrcKHR)
.setSrcAccessMask(vk::AccessFlagBits::eMemoryRead)
.setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
commandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eTransfer,
{},
nullptr,
nullptr,
barrier,
presentBarrier,
dispatcher);
}
}