mirror of
				https://github.com/PancakeTAS/lsfg-vk.git
				synced 2025-10-30 07:01:10 +00:00 
			
		
		
		
	refactor: vkd struct & buffer pool
This commit is contained in:
		
							parent
							
								
									83ec052f73
								
							
						
					
					
						commit
						24f7b66e99
					
				
					 9 changed files with 266 additions and 78 deletions
				
			
		|  | @ -1,17 +1,8 @@ | |||
| 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-framegen | ||||
|     DESCRIPTION "Lossless Scaling Frame Generation Backend" | ||||
|     LANGUAGES C CXX) | ||||
|     LANGUAGES C CXX) # FIXME: get rid of c language | ||||
| 
 | ||||
| file(GLOB SOURCES | ||||
|     "src/trans/*.cpp" | ||||
|  | @ -26,38 +17,37 @@ file(GLOB SOURCES | |||
| 
 | ||||
| add_library(lsfg-vk-framegen STATIC ${SOURCES}) | ||||
| 
 | ||||
| # target | ||||
| set_target_properties(lsfg-vk-framegen PROPERTIES | ||||
|     CXX_STANDARD 20 | ||||
|     CXX_STANDARD_REQUIRED ON) | ||||
|     CXX_STANDARD_REQUIRED ON | ||||
|     CXX_VISIBILITY_PRESET "hidden" | ||||
|     EXPORT_COMPILE_COMMANDS ON) | ||||
| target_include_directories(lsfg-vk-framegen SYSTEM | ||||
|     PUBLIC include/thirdparty) | ||||
| target_include_directories(lsfg-vk-framegen | ||||
|     PUBLIC include) | ||||
| 
 | ||||
| # diagnostics | ||||
| if(CMAKE_BUILD_TYPE STREQUAL "Debug") | ||||
|     set_target_properties(lsfg-vk-framegen PROPERTIES | ||||
|         EXPORT_COMPILE_COMMANDS ON) | ||||
| endif() | ||||
|     if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | ||||
|         message(WARNING "Debug builds should use Clang for better diagnostics") | ||||
|     else() | ||||
|         message(STATUS "Building with further diagnostics") | ||||
| 
 | ||||
| if(LSFGVK_EXCESS_DEBUG) | ||||
|     target_compile_options(lsfg-vk-framegen 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-cast-function-type-strict # for vulkan | ||||
|     ) | ||||
|         set_target_properties(lsfg-vk-framegen PROPERTIES | ||||
|             CXX_CLANG_TIDY clang-tidy) | ||||
| 
 | ||||
|     set_target_properties(lsfg-vk-framegen PROPERTIES | ||||
|         CXX_CLANG_TIDY clang-tidy) | ||||
|         target_compile_options(lsfg-vk-framegen PRIVATE | ||||
|             -Weverything | ||||
|             # disable incompatible warnings | ||||
|             -Wno-pre-c++20-compat-pedantic | ||||
|             -Wno-c++98-compat | ||||
|             -Wno-switch-default | ||||
|             -Wno-switch-enum | ||||
|             # disable noisy warnings | ||||
|             -Wno-missing-designated-field-initializers | ||||
|             -Wno-cast-function-type-strict | ||||
|             -Wno-padded | ||||
|             -Wno-shadow | ||||
|         ) | ||||
|     endif() | ||||
| endif() | ||||
|  |  | |||
|  | @ -7,10 +7,24 @@ | |||
| #include "vk/registry/shader_registry.hpp" | ||||
| 
 | ||||
| #include <filesystem> | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace LSFG { | ||||
| 
 | ||||
|     // FIXME: device picking
 | ||||
|     // FIXME: device picking, fp16 logic, etc.
 | ||||
| 
 | ||||
|     /// Vulkan (and related) data structure.
 | ||||
|     struct VKD { | ||||
|         VK::Core::Instance instance; | ||||
|         VK::Core::Device device; | ||||
|         VK::Core::DescriptorPool dpool; | ||||
| 
 | ||||
|         VK::Registry::ShaderRegistry registry; | ||||
| 
 | ||||
|         VK::Pool::ShaderPool spool; | ||||
| 
 | ||||
|         float flow{1.0F}; | ||||
|     }; | ||||
| 
 | ||||
|     ///
 | ||||
|     /// Lossless Scaling Frame Generation instance.
 | ||||
|  | @ -25,15 +39,8 @@ namespace LSFG { | |||
|         /// @throws LSFG::error if lsfg creation fails.
 | ||||
|         ///
 | ||||
|         Instance(const std::filesystem::path& dll); | ||||
| 
 | ||||
|     private: | ||||
|         VK::Core::Instance vk; | ||||
|         VK::Core::Device vkd; | ||||
| 
 | ||||
|         VK::Core::DescriptorPool pool; | ||||
| 
 | ||||
|         VK::Registry::ShaderRegistry registry; | ||||
|         VK::Pool::ShaderPool shaders; | ||||
|         std::unique_ptr<VKD> vkd; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
							
								
								
									
										22
									
								
								framegen/include/v31n/shaderchain/mipmaps.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								framegen/include/v31n/shaderchain/mipmaps.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include "vk/types/images.hpp" | ||||
| #include "vk/types/shader.hpp" | ||||
| 
 | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace LSFG { struct VKD; } | ||||
| namespace LSFG::V31N::Shaderchain { | ||||
| 
 | ||||
|     class Mipmaps { | ||||
|     public: | ||||
|         Mipmaps(VKD& vkd, | ||||
|             const VK::Core::Image& in1, | ||||
|             const VK::Core::Image& in2); | ||||
|     private: | ||||
|         std::unique_ptr<VK::Types::Shader> shader; | ||||
| 
 | ||||
|         VK::Types::Images<7> mipmaps; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										39
									
								
								framegen/include/vk/pool/buffer_pool.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								framegen/include/vk/pool/buffer_pool.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include "vk/core/buffer.hpp" | ||||
| 
 | ||||
| #include <unordered_map> | ||||
| #include <cstdint> | ||||
| 
 | ||||
| namespace VK::Pool { | ||||
| 
 | ||||
|     ///
 | ||||
|     /// Pool of initialized buffers.
 | ||||
|     ///
 | ||||
|     class BufferPool { | ||||
|     public: | ||||
|         ///
 | ||||
|         /// Create a buffer pool.
 | ||||
|         ///
 | ||||
|         BufferPool() noexcept = default; | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Get or create a buffer.
 | ||||
|         ///
 | ||||
|         /// @param flow Flow scale
 | ||||
|         /// @param hdr Whether HDR is enabled
 | ||||
|         /// @param timestamp Timestamp of the frame
 | ||||
|         /// @param firstIter Whether this is the first iteration
 | ||||
|         /// @param firstIterS Whether this is the first iteration for the second pass
 | ||||
|         /// @return Preallocated buffer
 | ||||
|         ///
 | ||||
|         /// @throws VK::vulkan_error if buffer creation fails.
 | ||||
|         ///
 | ||||
|         [[nodiscard]] const Core::Buffer& getOrCreate( | ||||
|             const Core::Device& device, float flow, bool hdr, | ||||
|             float timestamp, bool firstIter, bool firstIterS); | ||||
|     private: | ||||
|         std::unordered_map<uint64_t, Core::Buffer> buffers; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
|  | @ -23,15 +23,28 @@ namespace VK::Types { | |||
|         /// Create a new shader instance.
 | ||||
|         ///
 | ||||
|         Shader(Pool::ShaderInstance shader, | ||||
|                 std::vector<Core::DescriptorSet> sets) | ||||
|             : shader(std::move(shader)), | ||||
|             sets(std::move(sets)) {} | ||||
|                 std::vector<Core::DescriptorSet> sets, | ||||
|                 std::vector<Core::Sampler> samplers, | ||||
|                 std::optional<Core::Buffer> buffer, | ||||
|                 std::vector<std::vector<std::optional<Core::Image>>> inputs, | ||||
|                 std::vector<std::vector<Core::Image>> outputs) | ||||
|             : shader(std::move(shader)), sets(std::move(sets)), | ||||
|               samplers(std::move(samplers)), | ||||
|               buffer(std::move(buffer)), | ||||
|               inputs(std::move(inputs)), | ||||
|               outputs(std::move(outputs)) {} | ||||
| 
 | ||||
| 
 | ||||
|         /// TODO: remaining methods
 | ||||
| 
 | ||||
|     private: | ||||
|         Pool::ShaderInstance shader; | ||||
|         std::vector<Core::DescriptorSet> sets; | ||||
| 
 | ||||
|         std::vector<Core::Sampler> samplers; | ||||
|         std::optional<Core::Buffer> buffer; | ||||
|         std::vector<std::vector<std::optional<Core::Image>>> inputs; | ||||
|         std::vector<std::vector<Core::Image>> outputs; | ||||
|     }; | ||||
| 
 | ||||
|     ///
 | ||||
|  |  | |||
|  | @ -1,43 +1,52 @@ | |||
| #include "lsfg.hpp" | ||||
| #include "vk/registry/shader_registry.hpp" | ||||
| #include "vk/pool/shader_pool.hpp" | ||||
| #include "vk/core/descriptorpool.hpp" | ||||
| #include "vk/core/instance.hpp" | ||||
| #include "vk/core/device.hpp" | ||||
| #include "trans/rsrc.hpp" | ||||
| #include "vk/core/buffer.hpp" | ||||
| #include "vk/core/image.hpp" | ||||
| #include "vk/core/sampler.hpp" | ||||
| #include "vk/types/shader.hpp" | ||||
| 
 | ||||
| #include <vulkan/vulkan_core.h> | ||||
| 
 | ||||
| #include <filesystem> | ||||
| #include <vector> | ||||
| #include <utility> | ||||
| #include <memory> | ||||
| 
 | ||||
| using namespace LSFG; | ||||
| using namespace VK; | ||||
| 
 | ||||
| Instance::Instance(const std::filesystem::path& dll) { | ||||
|     VKD vkd{ | ||||
|         .instance = Core::Instance(), | ||||
|         .device = Core::Device(vkd.instance, 0, false), | ||||
|         .dpool = Core::DescriptorPool(vkd.device), | ||||
|         .registry = Registry::ShaderRegistry(), | ||||
|         .spool = Pool::ShaderPool() | ||||
|     }; | ||||
|     this->vkd = std::make_unique<VKD>(std::move(vkd)); | ||||
| 
 | ||||
| Instance::Instance(const std::filesystem::path& dll) | ||||
|         : vkd(vk, 0, false), pool(vkd) { | ||||
|     // load shaders from dll file
 | ||||
|     const bool fp16 = vkd.supportsFP16(); | ||||
|     Trans::RSRC::loadResources(dll, this->registry, fp16); | ||||
|     const bool fp16 = this->vkd->device.supportsFP16(); | ||||
|     Trans::RSRC::loadResources(dll, this->vkd->registry, fp16); | ||||
| 
 | ||||
|     // ...
 | ||||
| 
 | ||||
|     const auto sampler1 = | ||||
|         VK::Core::Sampler(vkd, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_COMPARE_OP_GREATER_OR_EQUAL, false); | ||||
|     const auto sampler2 = | ||||
|         VK::Core::Sampler(vkd, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_ALWAYS, true); | ||||
|     const auto buffer0 = | ||||
|         VK::Core::Buffer(vkd, 256, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); | ||||
|     const auto input0 = | ||||
|         VK::Core::Image(vkd, { 1920, 1080 }); | ||||
|     const auto input1 = | ||||
|         VK::Core::Image(vkd, { 1920, 1080 }); | ||||
|     const std::vector<VK::Core::Image> mipmaps{ | ||||
|         input0, input0 | ||||
|     }; | ||||
|     // const auto sampler1 =
 | ||||
|     //     VK::Core::Sampler(vkd, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_COMPARE_OP_GREATER_OR_EQUAL, false);
 | ||||
|     // const auto sampler2 =
 | ||||
|     //     VK::Core::Sampler(vkd, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_ALWAYS, true);
 | ||||
|     // const auto buffer0 =
 | ||||
|     //     VK::Core::Buffer(vkd, 256, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
 | ||||
|     // const auto input0 =
 | ||||
|     //     VK::Core::Image(vkd, { 1920, 1080 });
 | ||||
|     // const auto input1 =
 | ||||
|     //     VK::Core::Image(vkd, { 1920, 1080 });
 | ||||
|     // const std::vector<VK::Core::Image> mipmaps{
 | ||||
|     //     input0, input0
 | ||||
|     // };
 | ||||
| 
 | ||||
|     auto shader = VK::Types::ShaderBuilder(vkd, registry, this->shaders, "alpha[0]") | ||||
|         .withSamplers(sampler1, sampler2) | ||||
|         .withBuffer(buffer0) | ||||
|         .addTemporalInput({ input0, input1 }) | ||||
|         .addOutputs(mipmaps) | ||||
|         .build(vkd, this->pool); | ||||
|     // auto shader = VK::Types::ShaderBuilder(vkd, registry, this->shaders, "alpha[0]")
 | ||||
|     //     .withSamplers(sampler1, sampler2)
 | ||||
|     //     .withBuffer(buffer0)
 | ||||
|     //     .addTemporalInput({ input0, input1 })
 | ||||
|     //     .addOutputs(mipmaps)
 | ||||
|     //     .build(vkd, this->pool);
 | ||||
| } | ||||
|  |  | |||
							
								
								
									
										48
									
								
								framegen/src/v31n/shaderchain/mipmaps.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								framegen/src/v31n/shaderchain/mipmaps.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| #include "v31n/shaderchain/mipmaps.hpp" | ||||
| #include "vk/types/shader.hpp" | ||||
| #include "vk/core/sampler.hpp" | ||||
| #include "vk/core/buffer.hpp" | ||||
| #include "vk/core/image.hpp" | ||||
| #include "lsfg.hpp" | ||||
| 
 | ||||
| #include <vulkan/vulkan_core.h> | ||||
| 
 | ||||
| #include <vector> | ||||
| 
 | ||||
| using namespace LSFG::V31N::Shaderchain; | ||||
| using namespace VK; | ||||
| 
 | ||||
| Mipmaps::Mipmaps(LSFG::VKD& vkd, const Core::Image& in1, const Core::Image& in2) { | ||||
|     // TODO: logic for buffer and sampler
 | ||||
|     Core::Sampler sampler{vkd.device, | ||||
|         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, | ||||
|         VK_COMPARE_OP_NEVER, | ||||
|         false}; | ||||
|     Core::Buffer buffer{vkd.device, nullptr, 0, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT}; | ||||
| 
 | ||||
|     // create output images
 | ||||
|     const VkExtent2D extent{ | ||||
|         .width = static_cast<uint32_t>( | ||||
|             static_cast<float>(in1.getExtent().width) / vkd.flow), | ||||
|         .height = static_cast<uint32_t>( | ||||
|             static_cast<float>(in1.getExtent().height) / vkd.flow) | ||||
|     }; | ||||
| 
 | ||||
|     std::vector<Core::Image> mipmapVector{}; | ||||
|     mipmapVector.reserve(7); | ||||
|     for (size_t i = 0; i < 7; i++) | ||||
|         mipmapVector.emplace_back(vkd.device, | ||||
|         VkExtent2D { extent.width >> i, extent.height >> i }, | ||||
|         VK_FORMAT_R8_UNORM); | ||||
|     this->mipmaps = VK::Types::Images<7>(mipmapVector); | ||||
| 
 | ||||
|     // create shaders
 | ||||
|     auto shader = Types::ShaderBuilder( | ||||
|             vkd.device, vkd.registry, vkd.spool, "mipmaps", 2) | ||||
|         .withSamplers(sampler) | ||||
|         .withBuffer(buffer) | ||||
|         .addTemporalInput({ in1, in2 }) | ||||
|         .addOutputs(this->mipmaps.all()) | ||||
|         .build(vkd.device, vkd.dpool); | ||||
|     this->shader = std::make_unique<Types::Shader>(std::move(shader)); | ||||
| } | ||||
							
								
								
									
										54
									
								
								framegen/src/vk/pool/buffer_pool.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								framegen/src/vk/pool/buffer_pool.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| #include "vk/pool/buffer_pool.hpp" | ||||
| #include "vk/core/buffer.hpp" | ||||
| #include "vk/core/device.hpp" | ||||
| 
 | ||||
| #include <vulkan/vulkan_core.h> | ||||
| 
 | ||||
| #include <cstdint> | ||||
| #include <utility> | ||||
| #include <array> | ||||
| 
 | ||||
| using namespace VK::Pool; | ||||
| 
 | ||||
| struct ConstantBuffer { | ||||
|     std::array<uint32_t, 2> inputOffset; | ||||
|     uint32_t firstIter; | ||||
|     uint32_t firstIterS; | ||||
|     uint32_t advancedColorKind; | ||||
|     uint32_t hdrSupport; | ||||
|     float resolutionInvScale; | ||||
|     float timestamp; | ||||
|     float uiThreshold; | ||||
|     std::array<uint32_t, 3> pad; | ||||
| }; | ||||
| 
 | ||||
| const VK::Core::Buffer& BufferPool::getOrCreate( | ||||
|         const Core::Device& device, float flow, bool hdr, | ||||
|         float timestamp, bool firstIter, bool firstIterS) { | ||||
|     uint64_t hash = 0; | ||||
|     const union { float f; uint32_t i; } u{ | ||||
|         .f = timestamp }; | ||||
|     hash |= u.i; // NOLINT
 | ||||
|     hash |= static_cast<uint64_t>(firstIter) << 32; | ||||
|     hash |= static_cast<uint64_t>(firstIterS) << 33; | ||||
| 
 | ||||
|     const auto it = buffers.find(hash); | ||||
|     if (it != buffers.end()) { | ||||
|         return it->second; | ||||
|     } | ||||
| 
 | ||||
|     // create buffer
 | ||||
|     const ConstantBuffer data{ | ||||
|         .inputOffset = { 0, 0 }, | ||||
|         .advancedColorKind = hdr ? 2U : 0U, | ||||
|         .hdrSupport = hdr, | ||||
|         .resolutionInvScale = flow, | ||||
|         .timestamp = timestamp, | ||||
|         .uiThreshold = 0.5F, | ||||
|     }; | ||||
| 
 | ||||
|     Core::Buffer buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
| 
 | ||||
|     const auto i = buffers.emplace(hash, std::move(buffer)); | ||||
|     return i.first->second; | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| #include "vk/types/shader.hpp" | ||||
|  #include "vk/types/shader.hpp" | ||||
| #include "vk/core/descriptorpool.hpp" | ||||
| #include "vk/core/descriptorset.hpp" | ||||
| #include "vk/core/sampler.hpp" | ||||
|  | @ -86,5 +86,11 @@ Shader ShaderBuilder::build(const Core::Device& vkd, | |||
|             std::move(this->inputs.at(i)), | ||||
|             std::move(this->outputs.at(i)), | ||||
|             this->samplers, this->buffer); | ||||
|     return { this->shader, std::move(sets) }; | ||||
|     return { | ||||
|         this->shader, std::move(sets), | ||||
|         std::move(this->samplers), | ||||
|         std::move(this->buffer), | ||||
|         std::move(this->inputs), | ||||
|         std::move(this->outputs) | ||||
|     }; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 PancakeTAS
						PancakeTAS