Я пытаюсь извлечь изображения из swapchain и конвертировать их, чтобы я мог создать из них видео.
Я пытаюсь переместить макет изображения с помощью буфера команд однократной отправки.После отправки буфера команд в очередь я получаю предупреждения и ошибки от слоев проверки о том, что макеты изображений неправильно отформатированы, но я четко установил барьер конвейера, используя все правильные параметры.
Это происходит, даже когда я перемещаю макеты текстур для своих объектов, но все прекрасно работает даже с этими предупреждениями.Я не могу прочитать содержимое извлеченного изображения из-за этой ошибки.
Что может быть причиной этого?Вот как я конвертирую макеты:
VkCommandBuffer cmdBuffer = commandBuffer == VK_NULL_HANDLE ?
CommandBufferHandler::createOneTimeUsageBuffer(commandPool, device) : commandBuffer;
VkImageMemoryBarrier barrier = {};
VkPipelineStageFlags sourceStage = {};
VkPipelineStageFlags dstStage = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = mipLevels;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
if (hasStencilComponent(format)) {
barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
}
else {
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_GENERAL) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else {
throw std::invalid_argument("unsupported layout transition!");
}
vkCmdPipelineBarrier(cmdBuffer, sourceStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
if (commandBuffer == VK_NULL_HANDLE) {
CommandBufferHandler::endOneTimeUsageBuffer(cmdBuffer, queue, commandPool, device);
}
А вот как я делаю снимок:
VkImageCreateInfo screenshotCreateInfo;
VkImage srcImage = images[activeImageSwapchainId];
VkDeviceMemory dstImageMemory;
VkImage dstImage = VK_NULL_HANDLE;
if (supportsBlit) {
VkCommandBuffer cmdBuffer = CommandBufferHandler::createOneTimeUsageBuffer(
mainWindow->getCommandHandler()->getCommandPool(), mainWindow->getRenderer()->getDevice());
Util::createImage(sizeX, sizeY, 1, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
&dstImage, &dstImageMemory, mainWindow->getRenderer()->getDevice(),
mainWindow->getRenderer()->getPhysicalDeviceMemoryPropertiesPTR());
Util::transitionImageLayout(dstImage,
VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
mainWindow->getCommandHandler()->getCommandPool(),
mainWindow->getRenderer()->getQueueIndices()->getQueue(),
mainWindow->getRenderer()->getDevice(),
1,
cmdBuffer);
Util::transitionImageLayout(srcImage,
VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
mainWindow->getCommandHandler()->getCommandPool(),
mainWindow->getRenderer()->getQueueIndices()->getQueue(),
mainWindow->getRenderer()->getDevice(),
1,
cmdBuffer);
VkOffset3D offsets{};
offsets.x = swapExtent.width;
offsets.y = swapExtent.height;
offsets.z = 1;
VkImageBlit blit{};
blit.srcSubresource.layerCount = 1;
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit.dstSubresource.layerCount = 1;
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit.srcOffsets[1] = offsets;
blit.dstOffsets[1] = offsets;
vkCmdBlitImage(cmdBuffer,
srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &blit, VK_FILTER_NEAREST);
Util::transitionImageLayout(dstImage, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
mainWindow->getCommandHandler()->getCommandPool(),
mainWindow->getRenderer()->getQueueIndices()->getQueue(),
mainWindow->getRenderer()->getDevice(),
1,
cmdBuffer);
Util::transitionImageLayout(srcImage, VK_FORMAT_B8G8R8A8_UNORM,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
mainWindow->getCommandHandler()->getCommandPool(),
mainWindow->getRenderer()->getQueueIndices()->getQueue(),
mainWindow->getRenderer()->getDevice(),
1,
cmdBuffer);
CommandBufferHandler::endOneTimeUsageBuffer(cmdBuffer, mainWindow->getRenderer()->getQueueIndices()->getQueue(),
mainWindow->getCommandHandler()->getCommandPool(), mainWindow->getRenderer()->getDevice());
VkImageSubresource subresource{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
VkSubresourceLayout subresourceLayout;
vkGetImageSubresourceLayout(mainWindow->getRenderer()->getDevice(), dstImage, &subresource, &subresourceLayout);
const char *data = nullptr;
vkMapMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data);
data += subresourceLayout.offset;
std::ofstream file(filePath, std::ios::out | std::ios::binary);
file << "P6\n" << swapExtent.width << "\n" << swapExtent.height << "\n" << 255 << "\n"; //File header
for (uint32_t y = 0; y < swapExtent.height; ++y) {
unsigned int *row = (unsigned int*)data;
for (uint32_t x = 0; x < swapExtent.width; ++x) {
file.write((char*)row, 3);
row++;
}
data += subresourceLayout.rowPitch;
}
file.close();
std::cout << "Screenshot saved to: " << filePath << std::endl;
vkUnmapMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory);
vkFreeMemory(mainWindow->getRenderer()->getDevice(), dstImageMemory, nullptr);
vkDestroyImage(mainWindow->getRenderer()->getDevice(), dstImage, nullptr);
}
else {
assert(0 && "Swapchain error: Your device does not support image blitting. Cannot save image. Will be patched.");
return;
}
Предупреждения такие же, как на изображении ниже.Все остальные предупреждения приходят от того, что мой макет изображения не был переведен.
Когда я использую Blit, я получаю эту ошибку.Я создаю dstImage
в формате VK_FORMAT_R8G8B8A8_UNORM
.