initial round of fixes

This commit is contained in:
PancakeTAS 2025-06-29 19:35:29 +02:00
parent 736fa9b74f
commit 6261a6ed6e
No known key found for this signature in database
10 changed files with 124 additions and 25 deletions

View file

@ -28,13 +28,13 @@ namespace Vulkan::Core {
/// @throws std::invalid_argument if the device or buffer size is invalid /// @throws std::invalid_argument if the device or buffer size is invalid
/// @throws ls::vulkan_error if object creation fails. /// @throws ls::vulkan_error if object creation fails.
/// ///
Buffer(const Device& device, uint32_t size, std::vector<uint8_t> data, Buffer(const Device& device, size_t size, std::vector<uint8_t> data,
VkBufferUsageFlags usage); VkBufferUsageFlags usage);
/// Get the Vulkan handle. /// Get the Vulkan handle.
[[nodiscard]] auto handle() const { return *this->buffer; } [[nodiscard]] auto handle() const { return *this->buffer; }
/// Get the size of the 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. /// Check whether the object is valid.
[[nodiscard]] bool isValid() const { return static_cast<bool>(this->buffer); } [[nodiscard]] bool isValid() const { return static_cast<bool>(this->buffer); }
@ -51,7 +51,7 @@ namespace Vulkan::Core {
std::shared_ptr<VkBuffer> buffer; std::shared_ptr<VkBuffer> buffer;
std::shared_ptr<VkDeviceMemory> memory; std::shared_ptr<VkDeviceMemory> memory;
uint32_t size; size_t size;
}; };
} }

View file

@ -10,9 +10,9 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <variant>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include <variant>
#include <memory> #include <memory>
namespace Vulkan::Core { namespace Vulkan::Core {
@ -31,7 +31,7 @@ namespace Vulkan::Core {
/// @param pool Descriptor pool to allocate from /// @param pool Descriptor pool to allocate from
/// @param shaderModule Shader module to use for the descriptor set /// @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. /// @throws ls::vulkan_error if object creation fails.
/// ///
DescriptorSet(const Device& device, DescriptorSet(const Device& device,

View file

@ -21,7 +21,7 @@ namespace Vulkan::Core {
/// ///
/// @param device Vulkan device /// @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. /// @throws ls::vulkan_error if object creation fails.
/// ///
Fence(const Device& device); Fence(const Device& device);
@ -29,7 +29,6 @@ namespace Vulkan::Core {
/// ///
/// Reset the fence to an unsignaled state. /// Reset the fence to an unsignaled state.
/// ///
/// @throws std::logic_error if the fence is not valid.
/// @throws ls::vulkan_error if resetting fails. /// @throws ls::vulkan_error if resetting fails.
/// ///
void reset() const; void reset() const;
@ -40,7 +39,6 @@ namespace Vulkan::Core {
/// @param timeout The timeout in nanoseconds, or UINT64_MAX for no timeout. /// @param timeout The timeout in nanoseconds, or UINT64_MAX for no timeout.
/// @returns true if the fence signaled, false if it timed out. /// @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. /// @throws ls::vulkan_error if waiting fails.
/// ///
[[nodiscard]] bool wait(uint64_t timeout = UINT64_MAX) const; [[nodiscard]] bool wait(uint64_t timeout = UINT64_MAX) const;

View file

@ -24,7 +24,7 @@ namespace Vulkan::Core {
/// @param device Vulkan device /// @param device Vulkan device
/// @param shader Shader module to use for the pipeline. /// @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. /// @throws ls::vulkan_error if object creation fails.
/// ///
Pipeline(const Device& device, const ShaderModule& shader); Pipeline(const Device& device, const ShaderModule& shader);

View file

@ -6,7 +6,7 @@
using namespace Vulkan::Core; using namespace Vulkan::Core;
Buffer::Buffer(const Device& device, uint32_t size, std::vector<uint8_t> data, Buffer::Buffer(const Device& device, size_t size, std::vector<uint8_t> data,
VkBufferUsageFlags usage) : size(size) { VkBufferUsageFlags usage) : size(size) {
if (!device) if (!device)
throw std::invalid_argument("Invalid Vulkan device"); throw std::invalid_argument("Invalid Vulkan device");

View file

@ -27,9 +27,6 @@ Fence::Fence(const Device& device) {
} }
void Fence::reset() const { void Fence::reset() const {
if (!this->isValid())
throw std::logic_error("Invalid fence");
VkFence fenceHandle = this->handle(); VkFence fenceHandle = this->handle();
auto res = vkResetFences(this->device, 1, &fenceHandle); auto res = vkResetFences(this->device, 1, &fenceHandle);
if (res != VK_SUCCESS) if (res != VK_SUCCESS)
@ -37,9 +34,6 @@ void Fence::reset() const {
} }
bool Fence::wait(uint64_t timeout) const { bool Fence::wait(uint64_t timeout) const {
if (!this->isValid())
throw std::logic_error("Invalid fence");
VkFence fenceHandle = this->handle(); VkFence fenceHandle = this->handle();
auto res = vkWaitForFences(this->device, 1, &fenceHandle, VK_TRUE, timeout); auto res = vkWaitForFences(this->device, 1, &fenceHandle, VK_TRUE, timeout);
if (res != VK_SUCCESS && res != VK_TIMEOUT) if (res != VK_SUCCESS && res != VK_TIMEOUT)

View file

@ -4,8 +4,8 @@
using namespace Vulkan::Core; using namespace Vulkan::Core;
Pipeline::Pipeline(const Device& device, const ShaderModule& shader) { Pipeline::Pipeline(const Device& device, const ShaderModule& shader) {
if (!device) if (!device || !shader)
throw std::invalid_argument("Invalid Vulkan device"); throw std::invalid_argument("Invalid Vulkan device or shader module");
// create pipeline layout // create pipeline layout
VkDescriptorSetLayout shaderLayout = shader.getDescriptorSetLayout(); VkDescriptorSetLayout shaderLayout = shader.getDescriptorSetLayout();

View file

@ -34,7 +34,7 @@ Semaphore::Semaphore(const Device& device, std::optional<uint32_t> initial) {
} }
void Semaphore::signal(uint64_t value) const { void Semaphore::signal(uint64_t value) const {
if (!this->isValid() || !this->isTimeline) if (!this->isTimeline)
throw std::logic_error("Invalid timeline semaphore"); throw std::logic_error("Invalid timeline semaphore");
const VkSemaphoreSignalInfo signalInfo{ const VkSemaphoreSignalInfo signalInfo{
@ -48,7 +48,7 @@ void Semaphore::signal(uint64_t value) const {
} }
bool Semaphore::wait(uint64_t value, uint64_t timeout) 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"); throw std::logic_error("Invalid timeline semaphore");
VkSemaphore semaphore = this->handle(); VkSemaphore semaphore = this->handle();

View file

@ -2,7 +2,6 @@
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
#include <fstream> #include <fstream>
#include <vector>
using namespace Vulkan::Core; using namespace Vulkan::Core;

View file

@ -1,31 +1,134 @@
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp" #include "core/commandbuffer.hpp"
#include "core/commandpool.hpp" #include "core/commandpool.hpp"
#include "core/descriptorpool.hpp"
#include "core/descriptorset.hpp"
#include "core/fence.hpp" #include "core/fence.hpp"
#include "core/image.hpp"
#include "core/pipeline.hpp" #include "core/pipeline.hpp"
#include "core/sampler.hpp"
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include "instance.hpp" #include "instance.hpp"
#include <algorithm>
#include <array>
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <vector>
#include <vulkan/vulkan_core.h>
using namespace Vulkan; using namespace Vulkan;
struct DataBuffer {
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 static DataBuffer data{
.inputOffset = { 0, 29 },
.resolutionInvScale = 1.0F,
.timestamp = 0.5,
.uiThreshold = 0.1F
};
int main() { int main() {
// initialize Vulkan // initialize Vulkan
const Instance instance; const Instance instance;
const Device device(instance); const Device device(instance);
// prepare render pass // load shader
const Core::CommandPool commandPool(device);
// prepare shader
const Core::ShaderModule computeShader(device, "shaders/downsample.spv", const Core::ShaderModule computeShader(device, "shaders/downsample.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER}, { { 1, VK_DESCRIPTOR_TYPE_SAMPLER},
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE}, { 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE},
{ 7, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE}, { 7, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE},
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER} }); { 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::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<Core::Image> 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<const uint8_t*>(&data);
std::vector<uint8_t> 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<Core::Image> 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 // start pass
Core::Fence fence(device); Core::Fence fence(device);
@ -33,6 +136,11 @@ int main() {
Core::CommandBuffer commandBuffer(device, commandPool); Core::CommandBuffer commandBuffer(device, commandPool);
commandBuffer.begin(); commandBuffer.begin();
// render
computePipeline.bind(commandBuffer);
descriptorSet.bind(commandBuffer, computePipeline);
commandBuffer.dispatch(40, 23, 1);
// end pass // end pass
commandBuffer.end(); commandBuffer.end();