From 6261a6ed6e9e87b890e0d83c047c995b76edc735 Mon Sep 17 00:00:00 2001 From: PancakeTAS Date: Sun, 29 Jun 2025 19:35:29 +0200 Subject: [PATCH] initial round of fixes --- include/core/buffer.hpp | 6 +- include/core/descriptorset.hpp | 4 +- include/core/fence.hpp | 4 +- include/core/pipeline.hpp | 2 +- src/core/buffer.cpp | 2 +- src/core/fence.cpp | 6 -- src/core/pipeline.cpp | 4 +- src/core/semaphore.cpp | 4 +- src/core/shadermodule.cpp | 1 - src/main.cpp | 116 +++++++++++++++++++++++++++++++-- 10 files changed, 124 insertions(+), 25 deletions(-) diff --git a/include/core/buffer.hpp b/include/core/buffer.hpp index fecf3e1..5f9ac61 100644 --- a/include/core/buffer.hpp +++ b/include/core/buffer.hpp @@ -28,13 +28,13 @@ namespace Vulkan::Core { /// @throws std::invalid_argument if the device or buffer size is invalid /// @throws ls::vulkan_error if object creation fails. /// - Buffer(const Device& device, uint32_t size, std::vector data, + Buffer(const Device& device, size_t size, std::vector data, VkBufferUsageFlags usage); /// Get the Vulkan handle. [[nodiscard]] auto handle() const { return *this->buffer; } /// Get the size of the buffer. - [[nodiscard]] uint32_t getSize() const { return this->size; } + [[nodiscard]] size_t getSize() const { return this->size; } /// Check whether the object is valid. [[nodiscard]] bool isValid() const { return static_cast(this->buffer); } @@ -51,7 +51,7 @@ namespace Vulkan::Core { std::shared_ptr buffer; std::shared_ptr memory; - uint32_t size; + size_t size; }; } diff --git a/include/core/descriptorset.hpp b/include/core/descriptorset.hpp index b2c2bf7..2bbb922 100644 --- a/include/core/descriptorset.hpp +++ b/include/core/descriptorset.hpp @@ -10,9 +10,9 @@ #include "core/shadermodule.hpp" #include "device.hpp" -#include #include +#include #include namespace Vulkan::Core { @@ -31,7 +31,7 @@ namespace Vulkan::Core { /// @param pool Descriptor pool to allocate from /// @param shaderModule Shader module to use for the descriptor set /// - /// @throws std::invalid_argument if the device or pool is invalid. + /// @throws std::invalid_argument if the device, pool or shader module is invalid. /// @throws ls::vulkan_error if object creation fails. /// DescriptorSet(const Device& device, diff --git a/include/core/fence.hpp b/include/core/fence.hpp index bb921bd..8900840 100644 --- a/include/core/fence.hpp +++ b/include/core/fence.hpp @@ -21,7 +21,7 @@ namespace Vulkan::Core { /// /// @param device Vulkan device /// - /// @throws std::invalid_argument if the device is null. + /// @throws std::invalid_argument if the device is invalid. /// @throws ls::vulkan_error if object creation fails. /// Fence(const Device& device); @@ -29,7 +29,6 @@ namespace Vulkan::Core { /// /// Reset the fence to an unsignaled state. /// - /// @throws std::logic_error if the fence is not valid. /// @throws ls::vulkan_error if resetting fails. /// void reset() const; @@ -40,7 +39,6 @@ namespace Vulkan::Core { /// @param timeout The timeout in nanoseconds, or UINT64_MAX for no timeout. /// @returns true if the fence signaled, false if it timed out. /// - /// @throws std::logic_error if the fence is not valid. /// @throws ls::vulkan_error if waiting fails. /// [[nodiscard]] bool wait(uint64_t timeout = UINT64_MAX) const; diff --git a/include/core/pipeline.hpp b/include/core/pipeline.hpp index 36c7a65..b51ec14 100644 --- a/include/core/pipeline.hpp +++ b/include/core/pipeline.hpp @@ -24,7 +24,7 @@ namespace Vulkan::Core { /// @param device Vulkan device /// @param shader Shader module to use for the pipeline. /// - /// @throws std::invalid_argument if the device is invalid. + /// @throws std::invalid_argument if the device or shader module is invalid. /// @throws ls::vulkan_error if object creation fails. /// Pipeline(const Device& device, const ShaderModule& shader); diff --git a/src/core/buffer.cpp b/src/core/buffer.cpp index 32e0e60..9ef9a78 100644 --- a/src/core/buffer.cpp +++ b/src/core/buffer.cpp @@ -6,7 +6,7 @@ using namespace Vulkan::Core; -Buffer::Buffer(const Device& device, uint32_t size, std::vector data, +Buffer::Buffer(const Device& device, size_t size, std::vector data, VkBufferUsageFlags usage) : size(size) { if (!device) throw std::invalid_argument("Invalid Vulkan device"); diff --git a/src/core/fence.cpp b/src/core/fence.cpp index a0ddd75..e864340 100644 --- a/src/core/fence.cpp +++ b/src/core/fence.cpp @@ -27,9 +27,6 @@ Fence::Fence(const Device& device) { } void Fence::reset() const { - if (!this->isValid()) - throw std::logic_error("Invalid fence"); - VkFence fenceHandle = this->handle(); auto res = vkResetFences(this->device, 1, &fenceHandle); if (res != VK_SUCCESS) @@ -37,9 +34,6 @@ void Fence::reset() const { } bool Fence::wait(uint64_t timeout) const { - if (!this->isValid()) - throw std::logic_error("Invalid fence"); - VkFence fenceHandle = this->handle(); auto res = vkWaitForFences(this->device, 1, &fenceHandle, VK_TRUE, timeout); if (res != VK_SUCCESS && res != VK_TIMEOUT) diff --git a/src/core/pipeline.cpp b/src/core/pipeline.cpp index 120c6f1..ac0cc31 100644 --- a/src/core/pipeline.cpp +++ b/src/core/pipeline.cpp @@ -4,8 +4,8 @@ using namespace Vulkan::Core; Pipeline::Pipeline(const Device& device, const ShaderModule& shader) { - if (!device) - throw std::invalid_argument("Invalid Vulkan device"); + if (!device || !shader) + throw std::invalid_argument("Invalid Vulkan device or shader module"); // create pipeline layout VkDescriptorSetLayout shaderLayout = shader.getDescriptorSetLayout(); diff --git a/src/core/semaphore.cpp b/src/core/semaphore.cpp index 0da15cb..7008764 100644 --- a/src/core/semaphore.cpp +++ b/src/core/semaphore.cpp @@ -34,7 +34,7 @@ Semaphore::Semaphore(const Device& device, std::optional initial) { } void Semaphore::signal(uint64_t value) const { - if (!this->isValid() || !this->isTimeline) + if (!this->isTimeline) throw std::logic_error("Invalid timeline semaphore"); const VkSemaphoreSignalInfo signalInfo{ @@ -48,7 +48,7 @@ void Semaphore::signal(uint64_t value) const { } bool Semaphore::wait(uint64_t value, uint64_t timeout) const { - if (!this->isValid() || !this->isTimeline) + if (!this->isTimeline) throw std::logic_error("Invalid timeline semaphore"); VkSemaphore semaphore = this->handle(); diff --git a/src/core/shadermodule.cpp b/src/core/shadermodule.cpp index 703b609..4d777b3 100644 --- a/src/core/shadermodule.cpp +++ b/src/core/shadermodule.cpp @@ -2,7 +2,6 @@ #include "utils/exceptions.hpp" #include -#include using namespace Vulkan::Core; diff --git a/src/main.cpp b/src/main.cpp index 69ea2cc..6094deb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,31 +1,134 @@ +#include "core/buffer.hpp" #include "core/commandbuffer.hpp" #include "core/commandpool.hpp" +#include "core/descriptorpool.hpp" +#include "core/descriptorset.hpp" #include "core/fence.hpp" +#include "core/image.hpp" #include "core/pipeline.hpp" +#include "core/sampler.hpp" #include "core/shadermodule.hpp" #include "device.hpp" #include "instance.hpp" +#include +#include #include #include +#include +#include using namespace Vulkan; +struct DataBuffer { + std::array inputOffset; + uint32_t firstIter; + uint32_t firstIterS; + uint32_t advancedColorKind; + uint32_t hdrSupport; + float resolutionInvScale; + float timestamp; + float uiThreshold; + std::array pad; +}; + +const static DataBuffer data{ + .inputOffset = { 0, 29 }, + .resolutionInvScale = 1.0F, + .timestamp = 0.5, + .uiThreshold = 0.1F +}; + int main() { // initialize Vulkan const Instance instance; const Device device(instance); - // prepare render pass - const Core::CommandPool commandPool(device); - - // prepare shader + // load shader const Core::ShaderModule computeShader(device, "shaders/downsample.spv", { { 1, VK_DESCRIPTOR_TYPE_SAMPLER}, { 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE}, { 7, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE}, { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER} }); + + // prepare render pass + const Core::CommandPool commandPool(device); + const Core::DescriptorPool descriptorPool(device); const Core::Pipeline computePipeline(device, computeShader); + const Core::DescriptorSet descriptorSet(device, descriptorPool, computeShader); + + // create shader inputs + const Core::Sampler sampler(device, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER); + + const std::vector images(1, Core::Image( + device, { 2560, 1411 }, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, + VK_IMAGE_ASPECT_COLOR_BIT + )); + + const auto* dataBuffer = reinterpret_cast(&data); + std::vector dataVec(sizeof(DataBuffer)); + std::copy_n(dataBuffer, sizeof(DataBuffer), dataVec.data()); + const Core::Buffer buffer(device, dataVec.size(), dataVec, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); + + // create shader outputs + const std::vector outputImages = { + Core::Image( + device, { 1280, 705 }, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT + ), + Core::Image( + device, { 640, 352 }, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT + ), + Core::Image( + device, { 320, 176 }, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT + ), + Core::Image( + device, { 160, 88 }, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT + ), + Core::Image( + device, { 80, 44 }, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT + ), + Core::Image( + device, { 40, 22 }, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT + ), + Core::Image( + device, { 20, 11 }, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT + ) + }; + + // load descriptor set + descriptorSet.update( + device, + { + {{ VK_DESCRIPTOR_TYPE_SAMPLER, sampler }}, + {{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, images[0] }}, + { + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[0] }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[1] }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[2] }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[3] }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[4] }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[5] }, + { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[6] } + }, + {{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer }} + } + ); // start pass Core::Fence fence(device); @@ -33,6 +136,11 @@ int main() { Core::CommandBuffer commandBuffer(device, commandPool); commandBuffer.begin(); + // render + computePipeline.bind(commandBuffer); + descriptorSet.bind(commandBuffer, computePipeline); + commandBuffer.dispatch(40, 23, 1); + // end pass commandBuffer.end();