mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-26 19:58:36 +01:00
Windows/Vulkan: implement screenshots. Something is iffy with the red/blue swap though...
This commit is contained in:
1 parent
3594623a8d
commit
10792cc8e7
10 files changed
+118
-27
No files matched your search
@@ -837,22 +837,6 @@ void VulkanQueueRunner::SetupTransitionToTransferDst(VKRImage &img, VkImageMemor
|
||||
}
|
||||
|
||||
void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd) {
|
||||
VKRImage *srcImage;
|
||||
if (step.readback.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
srcImage = &step.readback.src->color;
|
||||
} else if (step.readback.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
srcImage = &step.readback.src->depth;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
VkPipelineStageFlags stage = 0;
|
||||
if (srcImage->layout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
|
||||
SetupTransitionToTransferSrc(*srcImage, barrier, stage, step.readback.aspectMask);
|
||||
vkCmdPipelineBarrier(cmd, stage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
}
|
||||
|
||||
ResizeReadbackBuffer(sizeof(uint32_t) * step.readback.srcRect.extent.width * step.readback.srcRect.extent.height);
|
||||
|
||||
VkBufferImageCopy region{};
|
||||
@@ -863,9 +847,55 @@ void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd
|
||||
region.bufferOffset = 0;
|
||||
region.bufferRowLength = step.readback.srcRect.extent.width;
|
||||
region.bufferImageHeight = step.readback.srcRect.extent.height;
|
||||
vkCmdCopyImageToBuffer(cmd, srcImage->image, srcImage->layout, readbackBuffer_, 1, ®ion);
|
||||
|
||||
VkImage image;
|
||||
VkImageLayout copyLayout;
|
||||
// Special case for backbuffer readbacks.
|
||||
if (step.readback.src == nullptr) {
|
||||
// We only take screenshots after the main render pass (anything else would be stupid) so we need to transition out of PRESENT,
|
||||
// and then back into it.
|
||||
TransitionImageLayout2(cmd, backbufferImage_, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0, VK_ACCESS_TRANSFER_READ_BIT);
|
||||
copyLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
image = backbufferImage_;
|
||||
} else {
|
||||
VKRImage *srcImage;
|
||||
if (step.readback.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
srcImage = &step.readback.src->color;
|
||||
}
|
||||
else if (step.readback.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
srcImage = &step.readback.src->depth;
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
VkPipelineStageFlags stage = 0;
|
||||
if (srcImage->layout != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
|
||||
SetupTransitionToTransferSrc(*srcImage, barrier, stage, step.readback.aspectMask);
|
||||
vkCmdPipelineBarrier(cmd, stage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
}
|
||||
image = srcImage->image;
|
||||
copyLayout = srcImage->layout;
|
||||
}
|
||||
|
||||
vkCmdCopyImageToBuffer(cmd, image, copyLayout, readbackBuffer_, 1, ®ion);
|
||||
|
||||
// NOTE: Can't read the buffer using the CPU here - need to sync first.
|
||||
|
||||
// If we copied from the backbuffer, transition it back.
|
||||
if (step.readback.src == nullptr) {
|
||||
// We only take screenshots after the main render pass (anything else would be stupid) so we need to transition out of PRESENT,
|
||||
// and then back into it.
|
||||
TransitionImageLayout2(cmd, backbufferImage_, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT, 0);
|
||||
copyLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanQueueRunner::PerformReadbackImage(const VKRStep &step, VkCommandBuffer cmd) {
|
||||
@@ -911,6 +941,8 @@ void VulkanQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataForm
|
||||
assert(res == VK_SUCCESS);
|
||||
if (srcFormat == Draw::DataFormat::R8G8B8A8_UNORM) {
|
||||
ConvertFromRGBA8888(pixels, (const uint8_t *)mappedData, pixelStride, width, width, height, destFormat);
|
||||
} else if (srcFormat == Draw::DataFormat::B8G8R8A8_UNORM) {
|
||||
ConvertFromBGRA8888(pixels, (const uint8_t *)mappedData, pixelStride, width, width, height, destFormat);
|
||||
} else if (srcFormat == destFormat) {
|
||||
uint8_t *dst = pixels;
|
||||
const uint8_t *src = (const uint8_t *)mappedData;
|
||||
|
||||
Reference in new issue
Block a user