Dump every lsfg stage and require null descriptors

This commit is contained in:
CamilleLaVey
2026-08-13 00:24:18 -04:00
parent 30be8a5e18
commit a18d2b5c05
6 changed files with 93 additions and 28 deletions
@@ -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<const u8> 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<const u8> 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<const u8> pixels, bool blue_first) {
const size_t pixel_count = static_cast<size_t>(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<VkDeviceSize>(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<u8> 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_t>(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<VkDeviceSize>(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<VkDeviceSize>(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
@@ -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;
@@ -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;
@@ -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);
}
@@ -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};
};
@@ -9,7 +9,7 @@
namespace Vulkan {
LsfgShaders::LsfgShaders(const Device& device) {
if (!device.IsVulkanMemoryModelSupported()) {
if (!device.IsVulkanMemoryModelSupported() || !device.HasNullDescriptor()) {
return;
}