mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-04-22 02:11:43 +00:00
refactor(cleanup): add primitive debug tool
This commit is contained in:
parent
96ae2c760c
commit
5ca9bc5de9
8 changed files with 272 additions and 188 deletions
|
|
@ -1,6 +1,10 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(lsfg-vk LANGUAGES CXX)
|
||||
|
||||
# === user facing options
|
||||
option(LSFGVK_BUILD_DEBUG_TOOL
|
||||
"Build the debug tool for testing and debugging" OFF)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
|
@ -18,7 +22,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||
-Weverything
|
||||
# disable incompatible warnings
|
||||
-Wno-pre-c++20-compat-pedantic
|
||||
-Wno-c++98-compat
|
||||
-Wno-c++98-compat-pedantic
|
||||
-Wno-switch-default
|
||||
-Wno-switch-enum
|
||||
# disable noisy warnings
|
||||
|
|
@ -30,5 +34,12 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(LSFGVK_BUILD_DEBUG_TOOL)
|
||||
add_compile_definitions(LSFGVK__RENDERDOC_INTEGRATION)
|
||||
endif()
|
||||
|
||||
add_subdirectory(lsfg-vk-common)
|
||||
add_subdirectory(lsfg-vk-backend)
|
||||
if(LSFGVK_BUILD_DEBUG_TOOL)
|
||||
add_subdirectory(lsfg-vk-debug)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../helpers/pointers.hpp"
|
||||
#include "buffer.hpp"
|
||||
#include "descriptor_set.hpp"
|
||||
#include "image.hpp"
|
||||
#include "shader.hpp"
|
||||
|
|
@ -57,6 +58,11 @@ namespace vk {
|
|||
/// @param vk the vulkan instance
|
||||
/// @throws ls::vulkan_error on failure
|
||||
void submit(const vk::Vulkan& vk) const;
|
||||
|
||||
/// copy buffer to image
|
||||
/// @param buffer the source buffer
|
||||
/// @param image the destination image
|
||||
void copyBufferToImage(const vk::Buffer& buffer, const vk::Image& image) const;
|
||||
private:
|
||||
ls::owned_ptr<VkCommandBuffer> commandBuffer;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/helpers/errors.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/descriptor_set.hpp"
|
||||
#include "lsfg-vk-common/vulkan/fence.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
|
@ -160,3 +161,43 @@ void CommandBuffer::submit(const vk::Vulkan& vk) const {
|
|||
if (!fence.wait(vk))
|
||||
throw ls::vulkan_error(VK_TIMEOUT, "Fence::wait() timed out");
|
||||
}
|
||||
|
||||
void CommandBuffer::copyBufferToImage(const vk::Buffer& buffer, const vk::Image& image) const {
|
||||
const VkImageMemoryBarrier barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_NONE,
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
.image = image.handle(),
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
};
|
||||
vkCmdPipelineBarrier(*this->commandBuffer,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &barrier
|
||||
);
|
||||
|
||||
const VkBufferImageCopy region{
|
||||
.bufferImageHeight = 0,
|
||||
.imageSubresource = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.layerCount = 1
|
||||
},
|
||||
.imageExtent = {
|
||||
.width = image.getExtent().width,
|
||||
.height = image.getExtent().height,
|
||||
.depth = 1
|
||||
}
|
||||
};
|
||||
vkCmdCopyBufferToImage(*this->commandBuffer,
|
||||
buffer.handle(), image.handle(),
|
||||
VK_IMAGE_LAYOUT_GENERAL, 1, ®ion
|
||||
);
|
||||
}
|
||||
|
|
|
|||
36
lsfg-vk-debug/.clang-tidy
Normal file
36
lsfg-vk-debug/.clang-tidy
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
Checks:
|
||||
# enable basic checks
|
||||
- "clang-analyzer-*"
|
||||
# configure performance checks
|
||||
- "performance-*"
|
||||
- "-performance-enum-size"
|
||||
# configure readability and bugprone checks
|
||||
- "readability-*"
|
||||
- "bugprone-*"
|
||||
- "misc-*"
|
||||
- "-readability-braces-around-statements"
|
||||
- "-readability-function-cognitive-complexity"
|
||||
- "-readability-identifier-length"
|
||||
- "-readability-implicit-bool-conversion"
|
||||
- "-readability-magic-numbers"
|
||||
- "-readability-math-missing-parentheses"
|
||||
- "-readability-named-parameter"
|
||||
- "-bugprone-easily-swappable-parameters"
|
||||
# configure modernization
|
||||
- "modernize-*"
|
||||
- "-modernize-use-trailing-return-type"
|
||||
# configure cppcoreguidelines
|
||||
- "cppcoreguidelines-*"
|
||||
- "-cppcoreguidelines-avoid-magic-numbers"
|
||||
- "-cppcoreguidelines-pro-type-reinterpret-cast"
|
||||
- "-cppcoreguidelines-macro-usage"
|
||||
# disable slow and pointless checks
|
||||
- "-modernize-use-std-numbers"
|
||||
- "-modernize-type-traits"
|
||||
- "-cppcoreguidelines-owning-memory"
|
||||
- "-cppcoreguidelines-macro-to-enum"
|
||||
- "-readability-container-contains"
|
||||
- "-bugprone-reserved-identifier"
|
||||
- "-bugprone-stringview-nullptr"
|
||||
- "-bugprone-standalone-empty"
|
||||
- "-misc-unused-using-decls"
|
||||
8
lsfg-vk-debug/CMakeLists.txt
Normal file
8
lsfg-vk-debug/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
set(DEBUG_SOURCES
|
||||
"src/debug.cpp")
|
||||
|
||||
add_executable(lsfg-vk-debug ${DEBUG_SOURCES})
|
||||
|
||||
target_link_libraries(lsfg-vk-debug
|
||||
PUBLIC lsfg-vk-common
|
||||
PUBLIC lsfg-vk-backend)
|
||||
169
lsfg-vk-debug/src/debug.cpp
Normal file
169
lsfg-vk-debug/src/debug.cpp
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
#include "lsfg-vk-backend/lsfgvk.hpp"
|
||||
#include "lsfg-vk-common/vulkan/buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/timeline_semaphore.hpp"
|
||||
#include "lsfg-vk-common/vulkan/vulkan.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <bits/time.h>
|
||||
#include <time.h> // NOLINT (thanks clang-tidy)
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
const VkExtent2D EXTENT = { 1920, 1080 };
|
||||
|
||||
namespace {
|
||||
/// returns the current time in microseconds
|
||||
uint64_t get_current_time_us() {
|
||||
struct timespec ts{};
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
|
||||
return static_cast<uint64_t>(ts.tv_sec) * 1000000UL
|
||||
+ static_cast<uint64_t>(ts.tv_nsec) / 1000UL;
|
||||
}
|
||||
/// uploads an image from a dds file
|
||||
void upload_image(
|
||||
const vk::Vulkan& vk,
|
||||
const vk::Image& image,
|
||||
const std::string& path
|
||||
) {
|
||||
// read image bytecode
|
||||
std::ifstream file(path.data(), std::ios::binary | std::ios::ate);
|
||||
if (!file.is_open())
|
||||
throw std::runtime_error("ifstream::ifstream() failed");
|
||||
|
||||
std::streamsize size = file.tellg();
|
||||
size -= 124 + 4; // dds header and magic bytes
|
||||
|
||||
std::vector<char> code(static_cast<size_t>(size));
|
||||
file.seekg(124 + 4, std::ios::beg);
|
||||
if (!file.read(code.data(), size))
|
||||
throw std::runtime_error("ifstream::read() failed");
|
||||
|
||||
file.close();
|
||||
|
||||
// upload to image
|
||||
const vk::Buffer stagingbuf{vk, code.data(), code.size(),
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT};
|
||||
|
||||
const vk::CommandBuffer cmdbuf{vk};
|
||||
cmdbuf.copyBufferToImage(stagingbuf, image);
|
||||
|
||||
const vk::TimelineSemaphore sema{vk, 0};
|
||||
cmdbuf.submit(vk, sema, 1, sema, 2);
|
||||
|
||||
sema.signal(vk, 1);
|
||||
if (!sema.wait(vk, 2))
|
||||
throw std::runtime_error("image upload failed");
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
const uint64_t time_us = get_current_time_us();
|
||||
|
||||
const vk::Vulkan vk{
|
||||
"lsfg-vk-debug", vk::version{1, 1, 0},
|
||||
"lsfg-vk-debug-engine", vk::version{1, 0, 0},
|
||||
[](const std::vector<VkPhysicalDevice>& devices) {
|
||||
return devices.front();
|
||||
}
|
||||
};
|
||||
|
||||
std::pair<int, int> srcfds{};
|
||||
const vk::Image frame_0{vk,
|
||||
EXTENT, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
std::nullopt,
|
||||
&srcfds.first
|
||||
};
|
||||
const vk::Image frame_1{vk,
|
||||
EXTENT, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
std::nullopt,
|
||||
&srcfds.second
|
||||
};
|
||||
|
||||
std::vector<vk::Image> destimgs{};
|
||||
std::vector<int> destfds{};
|
||||
for (size_t i = 0; i < 1; i++) {
|
||||
int fd{};
|
||||
destimgs.emplace_back(vk,
|
||||
EXTENT, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
std::nullopt,
|
||||
&fd
|
||||
);
|
||||
destfds.push_back(fd);
|
||||
}
|
||||
|
||||
int syncfd{};
|
||||
const vk::TimelineSemaphore sync{vk, 0, std::nullopt, &syncfd};
|
||||
|
||||
const uint64_t init_done_us = get_current_time_us();
|
||||
std::cerr << "vulkan initialized in "
|
||||
<< (init_done_us - time_us) << "us\n";
|
||||
|
||||
// initialize lsfg-vk
|
||||
lsfgvk::Instance lsfgvk{
|
||||
[](const std::string&) {
|
||||
return true;
|
||||
},
|
||||
"/home/pancake/.steam/steam/steamapps/common/Lossless Scaling/Lossless.dll",
|
||||
true
|
||||
};
|
||||
lsfgvk::Context& lsfgvk_ctx = lsfgvk.openContext(
|
||||
srcfds, destfds,
|
||||
syncfd, EXTENT.width, EXTENT.height,
|
||||
false, 1.0F / 0.5F, true
|
||||
);
|
||||
|
||||
const uint64_t lsfg_init_done_us = get_current_time_us();
|
||||
std::cerr << "lsfg-vk initialized in "
|
||||
<< (lsfg_init_done_us - init_done_us) << "us\n";
|
||||
|
||||
// render destination images
|
||||
size_t idx{1};
|
||||
for (size_t j = 0; j < 3; j++) {
|
||||
try {
|
||||
upload_image(vk,
|
||||
j % 2 == 0 ? frame_0 : frame_1,
|
||||
"s" + std::to_string(j + 1) + ".dds"
|
||||
);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "failed to upload image: " << e.what() << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
sync.signal(vk, idx++);
|
||||
lsfgvk.scheduleFrames(lsfgvk_ctx);
|
||||
|
||||
for (size_t i = 0; i < destimgs.size(); i++) {
|
||||
auto success = sync.wait(vk, idx++);
|
||||
if (!success) {
|
||||
std::cerr << "failed to wait for frame " << j << ":" << i << "\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const uint64_t frame_done_us = get_current_time_us();
|
||||
std::cerr << "frame " << j << ":" << i << " done after "
|
||||
<< (frame_done_us - lsfg_init_done_us) << "us\n";
|
||||
}
|
||||
}
|
||||
|
||||
// deinitialize lsfg-vk
|
||||
lsfgvk.closeContext(lsfgvk_ctx);
|
||||
return EXIT_SUCCESS; // let the vulkan objects go out of scope
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
if(NOT LSFGVK_EXCESS_DEBUG)
|
||||
set(CMAKE_C_VISIBILITY_PRESET "hidden")
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
|
||||
endif()
|
||||
|
||||
if(LSFGVK_EXCESS_DEBUG)
|
||||
add_compile_definitions(LSFGVK_EXCESS_DEBUG)
|
||||
endif()
|
||||
|
||||
project(lsfg-vk-test
|
||||
DESCRIPTION "Test: lsfg-vk"
|
||||
LANGUAGES CXX)
|
||||
|
||||
file(GLOB SOURCES
|
||||
"src/*.cpp"
|
||||
)
|
||||
|
||||
add_executable(lsfg-vk-test ${SOURCES})
|
||||
|
||||
# target
|
||||
set_target_properties(lsfg-vk-test PROPERTIES
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED ON)
|
||||
target_link_libraries(lsfg-vk-test PUBLIC
|
||||
lsfg-vk lsfg-vk-framegen
|
||||
vulkan)
|
||||
|
||||
# diagnostics
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set_target_properties(lsfg-vk-test PROPERTIES
|
||||
EXPORT_COMPILE_COMMANDS ON)
|
||||
endif()
|
||||
|
||||
if(LSFGVK_EXCESS_DEBUG)
|
||||
target_compile_options(lsfg-vk-test PRIVATE
|
||||
-Weverything
|
||||
# disable compat c++ flags
|
||||
-Wno-pre-c++20-compat-pedantic
|
||||
-Wno-pre-c++17-compat
|
||||
-Wno-c++98-compat-pedantic
|
||||
-Wno-c++98-compat
|
||||
# disable other flags
|
||||
-Wno-missing-designated-field-initializers
|
||||
-Wno-shadow # allow shadowing
|
||||
-Wno-switch-enum # ignore missing cases
|
||||
-Wno-switch-default # ignore missing default
|
||||
-Wno-padded # ignore automatic padding
|
||||
-Wno-exit-time-destructors # allow globals
|
||||
-Wno-global-constructors # allow globals
|
||||
-Wno-cast-function-type-strict # for vulkan
|
||||
)
|
||||
|
||||
set_target_properties(lsfg-vk-test PROPERTIES
|
||||
CXX_CLANG_TIDY clang-tidy)
|
||||
endif()
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
#include "common/utils.hpp"
|
||||
#include "core/commandpool.hpp"
|
||||
#include "core/device.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/instance.hpp"
|
||||
#include "extract/extract.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
// test configuration
|
||||
|
||||
const VkExtent2D SRC_EXTENT = { 2560 , 1440 };
|
||||
const VkFormat SRC_FORMAT = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
const std::array<std::string, 3> SRC_FILES = {
|
||||
"test/f0.dds",
|
||||
"test/f1.dds",
|
||||
"test/f2.dds"
|
||||
};
|
||||
|
||||
const size_t MULTIPLIER = 3;
|
||||
const bool IS_HDR = false;
|
||||
const float FLOW_SCALE = 0.7F;
|
||||
#define PERFORMANCE_MODE false
|
||||
|
||||
// test configuration end
|
||||
|
||||
#if PERFORMANCE_MODE
|
||||
#include "lsfg_3_1p.hpp"
|
||||
using namespace LSFG_3_1P;
|
||||
#else
|
||||
#include "lsfg_3_1.hpp"
|
||||
using namespace LSFG_3_1;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
/// Create images for frame generation
|
||||
std::pair<Core::Image, Core::Image> create_images(const Core::Device& device,
|
||||
std::array<int, 2>& fds,
|
||||
std::vector<int>& outFds, std::vector<Core::Image>& out_n) {
|
||||
const Core::Image frame_0{device,
|
||||
SRC_EXTENT, SRC_FORMAT,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
&fds.at(0)
|
||||
};
|
||||
const Core::Image frame_1{device,
|
||||
SRC_EXTENT, SRC_FORMAT,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
&fds.at(1)
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < (MULTIPLIER - 1); i++)
|
||||
out_n.at(i) = Core::Image{device,
|
||||
SRC_EXTENT, SRC_FORMAT,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
&outFds.at(i)
|
||||
};
|
||||
|
||||
return { frame_0, frame_1 };
|
||||
}
|
||||
|
||||
/// Create the LSFG context.
|
||||
int32_t create_lsfg(const std::array<int, 2>& fds, const std::vector<int>& outFds) {
|
||||
Extract::extractShaders();
|
||||
initialize(
|
||||
0x1463ABAC,
|
||||
IS_HDR, 1.0F / FLOW_SCALE, MULTIPLIER - 1,
|
||||
false,
|
||||
Extract::getShader
|
||||
);
|
||||
initializeRenderDoc();
|
||||
return createContext(
|
||||
fds.at(0), fds.at(1), outFds,
|
||||
SRC_EXTENT, SRC_FORMAT
|
||||
);
|
||||
}
|
||||
|
||||
/// Destroy the LSFG context.
|
||||
void delete_lsfg(int32_t id) {
|
||||
deleteContext(id);
|
||||
finalize();
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::array<int, 2> fds{};
|
||||
std::vector<int> outFds(MULTIPLIER - 1);
|
||||
std::pair<Core::Image, Core::Image> frames{};
|
||||
std::vector<Core::Image> out_n(MULTIPLIER - 1);
|
||||
int32_t lsfg_id{};
|
||||
}
|
||||
|
||||
int main() {
|
||||
// initialize host Vulkan
|
||||
const Core::Instance instance{};
|
||||
const Core::Device device{instance, 0x1463ABAC, false};
|
||||
const Core::CommandPool commandPool{device};
|
||||
|
||||
// setup test
|
||||
frames = create_images(device, fds, outFds, out_n);
|
||||
lsfg_id = create_lsfg(fds, outFds);
|
||||
|
||||
Utils::clearImage(device, frames.first);
|
||||
Utils::clearImage(device, frames.second);
|
||||
|
||||
// run
|
||||
for (size_t fc = 0; fc < SRC_FILES.size(); fc++) {
|
||||
if (fc % 2 == 0)
|
||||
Utils::uploadImage(device, commandPool, frames.first, SRC_FILES.at(fc));
|
||||
else
|
||||
Utils::uploadImage(device, commandPool, frames.second, SRC_FILES.at(fc));
|
||||
|
||||
// run the present
|
||||
presentContext(lsfg_id, -1, {});
|
||||
}
|
||||
|
||||
// destroy test
|
||||
delete_lsfg(lsfg_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue