diff --git a/src/video_core/renderer_vulkan/present/frame_gen.cpp b/src/video_core/renderer_vulkan/present/frame_gen.cpp index ff66ee5def..1a22a0fa91 100644 --- a/src/video_core/renderer_vulkan/present/frame_gen.cpp +++ b/src/video_core/renderer_vulkan/present/frame_gen.cpp @@ -25,6 +25,17 @@ bool IsBlueFirst(VkFormat format) { return format == VK_FORMAT_B8G8R8A8_UNORM || format == VK_FORMAT_B8G8R8A8_SRGB; } +VkDeviceSize BytesPerTexel(VkFormat format) { + switch (format) { + case VK_FORMAT_R8_UNORM: + return 1; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return 8; + default: + return COLOR_CHANNELS; + } +} + void WritePortablePixmap(const std::filesystem::path& path, const std::string& magic, VkExtent2D extent, std::span pixels) { Common::FS::IOFile file{path, Common::FS::FileAccessMode::Write, @@ -49,6 +60,16 @@ void WriteGrayscalePgm(const std::filesystem::path& path, VkExtent2D extent, WritePortablePixmap(path, "P5", extent, pixels.subspan(0, std::min(expected, pixels.size()))); } +void WriteRaw(const std::filesystem::path& path, std::span pixels) { + Common::FS::IOFile file{path, Common::FS::FileAccessMode::Write, + Common::FS::FileType::BinaryFile}; + if (!file.IsOpen()) { + return; + } + void(file.Write(pixels)); + void(file.Flush()); +} + void WriteColorPpm(const std::filesystem::path& path, VkExtent2D extent, std::span pixels, bool blue_first) { const size_t pixel_count = static_cast(extent.width) * extent.height; @@ -175,7 +196,7 @@ void FrameGen::Process(const Device& device, Frame* frame, VkFormat format) { if (!dump_requested) { dumped = false; } else if (!dumped) { - DumpDebugImages(); + DumpDebugImages(count); dumped = true; } } @@ -189,46 +210,65 @@ void FrameGen::Rebuild(const Device& device, VkExtent2D extent, VkFormat format) frame_count = 0; } -void FrameGen::DumpDebugImages() { +void FrameGen::DumpDebugImages(u64 count) { const std::filesystem::path directory = Common::FS::GetEdenPath(Common::FS::EdenPath::LosslessDir) / "debug"; if (!Common::FS::CreateDirs(directory)) { return; } - const auto readback = [&](LsfgImage& image, VkDeviceSize size) { - vk::Buffer buffer = CreateWrappedBuffer(memory_allocator, size, MemoryUsage::Download); + const auto dump = [&](const std::string& name, LsfgImage& image) { const VkExtent2D extent = image.Extent(); + const VkFormat format = image.Format(); + const VkDeviceSize texel_size = BytesPerTexel(format); + const VkDeviceSize size = + static_cast(extent.width) * extent.height * texel_size; + + vk::Buffer buffer = CreateWrappedBuffer(memory_allocator, size, MemoryUsage::Download); scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([handle = image.Handle(), dst = *buffer, - extent](vk::CommandBuffer cmdbuf) { - DownloadColorImage(cmdbuf, handle, dst, - VkExtent3D{.width = extent.width, - .height = extent.height, - .depth = 1}); - }); + scheduler.Record( + [handle = image.Handle(), dst = *buffer, extent](vk::CommandBuffer cmdbuf) { + DownloadColorImage( + cmdbuf, handle, dst, + VkExtent3D{.width = extent.width, .height = extent.height, .depth = 1}); + }); scheduler.Finish(); buffer.Invalidate(); - return buffer; + const std::span mapped = buffer.Mapped(); + + if (format == LSFG_FLOW_FORMAT) { + WriteGrayscalePgm(directory / (name + ".pgm"), extent, mapped); + } else if (texel_size == COLOR_CHANNELS) { + WriteColorPpm(directory / (name + ".ppm"), extent, mapped, IsBlueFirst(format)); + } else { + WriteRaw(directory / (name + "_" + std::to_string(extent.width) + "x" + + std::to_string(extent.height) + ".f16"), + mapped.subspan(0, std::min(size, mapped.size()))); + } }; + dump("in0", chain->Input(0)); + dump("in1", chain->Input(1)); + for (size_t level = 0; level < LSFG_MIP_LEVELS; ++level) { - LsfgImage& image = chain->FlowLevel(level); - const VkExtent2D extent = image.Extent(); - const VkDeviceSize size = static_cast(extent.width) * extent.height; - vk::Buffer buffer = readback(image, size); - WriteGrayscalePgm(directory / ("flow_mip" + std::to_string(level) + ".pgm"), extent, - buffer.Mapped()); + dump("flow_mip" + std::to_string(level), chain->FlowLevel(level)); + } + for (size_t index = 0; index < 2; ++index) { + dump("alpha0_" + std::to_string(index), chain->AlphaOutput(0, count, index)); + dump("alpha6_" + std::to_string(index), chain->AlphaOutput(LSFG_MIP_LEVELS - 1, count, + index)); + } + for (size_t level = 0; level < LSFG_BETA_OUTPUTS; ++level) { + dump("beta_" + std::to_string(level), chain->BetaOutput(level)); } - LsfgImage& output = chain->Output(); - const VkExtent2D extent = output.Extent(); - const VkDeviceSize size = - static_cast(extent.width) * extent.height * COLOR_CHANNELS; - vk::Buffer buffer = readback(output, size); - WriteColorPpm(directory / "generated.ppm", extent, buffer.Mapped(), IsBlueFirst(built_format)); + dump("gamma0", chain->GammaOutput(0)); + dump("gamma6", chain->GammaOutput(LSFG_MIP_LEVELS - 1)); + dump("delta2_out1", chain->DeltaOutput1(LSFG_DELTA_INSTANCES - 1)); + dump("delta2_out2", chain->DeltaOutput2(LSFG_DELTA_INSTANCES - 1)); + dump("generated", chain->Output()); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/frame_gen.h b/src/video_core/renderer_vulkan/present/frame_gen.h index b2c3c95531..5d43e6ae75 100644 --- a/src/video_core/renderer_vulkan/present/frame_gen.h +++ b/src/video_core/renderer_vulkan/present/frame_gen.h @@ -25,7 +25,7 @@ public: private: void Rebuild(const Device& device, VkExtent2D extent, VkFormat format); - void DumpDebugImages(); + void DumpDebugImages(u64 count); MemoryAllocator& memory_allocator; Scheduler& scheduler; diff --git a/src/video_core/renderer_vulkan/present/lsfg_chain.h b/src/video_core/renderer_vulkan/present/lsfg_chain.h index be8026ea71..91f58ed13a 100644 --- a/src/video_core/renderer_vulkan/present/lsfg_chain.h +++ b/src/video_core/renderer_vulkan/present/lsfg_chain.h @@ -43,6 +43,26 @@ public: return mipmaps.Output(level); } + [[nodiscard]] LsfgImage& AlphaOutput(size_t level, u64 frame_count, size_t index) { + return alpha[level].Outputs()[frame_count % LSFG_HISTORY_SLOTS][index]; + } + + [[nodiscard]] LsfgImage& BetaOutput(size_t level) { + return beta.Output(level); + } + + [[nodiscard]] LsfgImage& GammaOutput(size_t index) { + return gamma[index].Output(); + } + + [[nodiscard]] LsfgImage& DeltaOutput1(size_t index) { + return delta[index].Output1(); + } + + [[nodiscard]] LsfgImage& DeltaOutput2(size_t index) { + return delta[index].Output2(); + } + private: LsfgResources resources; vk::DescriptorPool descriptor_pool; diff --git a/src/video_core/renderer_vulkan/present/lsfg_common.cpp b/src/video_core/renderer_vulkan/present/lsfg_common.cpp index 17fab47931..c84bf544c5 100644 --- a/src/video_core/renderer_vulkan/present/lsfg_common.cpp +++ b/src/video_core/renderer_vulkan/present/lsfg_common.cpp @@ -89,8 +89,8 @@ VkImageMemoryBarrier MakeBarrier(const LsfgImage& image, VkAccessFlags src_acces } // Anonymous namespace LsfgImage::LsfgImage(const Device& device, MemoryAllocator& memory_allocator, VkExtent2D extent_, - VkFormat format) - : extent{std::max(1u, extent_.width), std::max(1u, extent_.height)} { + VkFormat format_) + : extent{std::max(1u, extent_.width), std::max(1u, extent_.height)}, format{format_} { image = CreateChainImage(memory_allocator, extent, format); view = CreateWrappedImageView(device, image, format); } diff --git a/src/video_core/renderer_vulkan/present/lsfg_common.h b/src/video_core/renderer_vulkan/present/lsfg_common.h index 3042e3d597..d53150d35b 100644 --- a/src/video_core/renderer_vulkan/present/lsfg_common.h +++ b/src/video_core/renderer_vulkan/present/lsfg_common.h @@ -45,6 +45,10 @@ public: return extent; } + [[nodiscard]] VkFormat Format() const { + return format; + } + [[nodiscard]] VkImageLayout Layout() const { return layout; } @@ -57,6 +61,7 @@ private: vk::Image image; vk::ImageView view; VkExtent2D extent{}; + VkFormat format{VK_FORMAT_UNDEFINED}; VkImageLayout layout{VK_IMAGE_LAYOUT_UNDEFINED}; }; diff --git a/src/video_core/renderer_vulkan/present/lsfg_shaders.cpp b/src/video_core/renderer_vulkan/present/lsfg_shaders.cpp index 73468bf874..59a8de8613 100644 --- a/src/video_core/renderer_vulkan/present/lsfg_shaders.cpp +++ b/src/video_core/renderer_vulkan/present/lsfg_shaders.cpp @@ -9,7 +9,7 @@ namespace Vulkan { LsfgShaders::LsfgShaders(const Device& device) { - if (!device.IsVulkanMemoryModelSupported()) { + if (!device.IsVulkanMemoryModelSupported() || !device.HasNullDescriptor()) { return; }