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 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);
/// 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<bool>(this->buffer); }
@ -51,7 +51,7 @@ namespace Vulkan::Core {
std::shared_ptr<VkBuffer> buffer;
std::shared_ptr<VkDeviceMemory> memory;
uint32_t size;
size_t size;
};
}

View file

@ -10,9 +10,9 @@
#include "core/shadermodule.hpp"
#include "device.hpp"
#include <variant>
#include <vulkan/vulkan_core.h>
#include <variant>
#include <memory>
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,

View file

@ -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;

View file

@ -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);

View file

@ -6,7 +6,7 @@
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) {
if (!device)
throw std::invalid_argument("Invalid Vulkan device");

View file

@ -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)

View file

@ -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();

View file

@ -34,7 +34,7 @@ Semaphore::Semaphore(const Device& device, std::optional<uint32_t> 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();

View file

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

View file

@ -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 <algorithm>
#include <array>
#include <cassert>
#include <iostream>
#include <vector>
#include <vulkan/vulkan_core.h>
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() {
// 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<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
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();