diff --git a/src/blue_noise.cpp b/src/blue_noise.cpp index 001ed09..eab8918 100644 --- a/src/blue_noise.cpp +++ b/src/blue_noise.cpp @@ -343,6 +343,91 @@ image::Bl dither::blue_noise(int width, int height, int threads, goto ENDOF_VULKAN; } } + + // Load shader. + std::vector shader; + { + std::ifstream ifs("compute.spv"); + if (!ifs.good()) { + std::clog << "WARNING: Failed to find compute.spv!\n"; + goto ENDOF_VULKAN; + } + ifs.seekg(0, std::ios_base::end); + auto size = ifs.tellg(); + shader.resize(size); + + ifs.seekg(0); + ifs.read(shader.data(), size); + ifs.close(); + } + + // create compute pipeline. + VkPipelineLayout compute_pipeline_layout; + VkPipeline compute_pipeline; + utility::Cleanup cleanup_pipeline_layout(utility::Cleanup::Nop{}); + utility::Cleanup cleanup_pipeline(utility::Cleanup::Nop{}); + { + VkShaderModuleCreateInfo shader_module_create_info{}; + shader_module_create_info.sType = + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_create_info.codeSize = shader.size(); + shader_module_create_info.pCode = + reinterpret_cast(shader.data()); + + VkShaderModule compute_shader_module; + if (vkCreateShaderModule(device, &shader_module_create_info, nullptr, + &compute_shader_module) != VK_SUCCESS) { + std::clog << "WARNING: Failed to create shader module!\n"; + goto ENDOF_VULKAN; + } + + utility::Cleanup cleanup_shader_module( + [device](void *ptr) { + vkDestroyShaderModule(device, *((VkShaderModule *)ptr), nullptr); + }, + &compute_shader_module); + + VkPipelineShaderStageCreateInfo compute_shader_stage_info{}; + compute_shader_stage_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + compute_shader_stage_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; + compute_shader_stage_info.module = compute_shader_module; + compute_shader_stage_info.pName = "main"; + + VkPipelineLayoutCreateInfo pipeline_layout_info{}; + pipeline_layout_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_info.setLayoutCount = 1; + pipeline_layout_info.pSetLayouts = &compute_desc_set_layout; + + if (vkCreatePipelineLayout(device, &pipeline_layout_info, nullptr, + &compute_pipeline_layout) != VK_SUCCESS) { + std::clog << "WARNING: Failed to create compute pipeline layout!\n"; + goto ENDOF_VULKAN; + } + cleanup_pipeline_layout = utility::Cleanup( + [device](void *ptr) { + vkDestroyPipelineLayout(device, *((VkPipelineLayout *)ptr), + nullptr); + }, + &compute_pipeline_layout); + + VkComputePipelineCreateInfo pipeline_info{}; + pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipeline_info.layout = compute_pipeline_layout; + pipeline_info.stage = compute_shader_stage_info; + + if (vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipeline_info, + nullptr, &compute_pipeline) != VK_SUCCESS) { + std::clog << "WARNING: Failed to create compute pipeline!\n"; + goto ENDOF_VULKAN; + } + cleanup_pipeline = utility::Cleanup( + [device](void *ptr) { + vkDestroyPipeline(device, *((VkPipeline *)ptr), nullptr); + }, + &compute_pipeline); + } } ENDOF_VULKAN: std::clog << "TODO: Remove this once Vulkan support is implemented.\n"; diff --git a/src/utility.cpp b/src/utility.cpp index 58dbebb..ea72296 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -3,4 +3,29 @@ utility::Cleanup::Cleanup(std::function fn, void *ptr) : fn(fn), ptr(ptr) {} -utility::Cleanup::~Cleanup() { this->fn(this->ptr); } +utility::Cleanup::Cleanup(Nop) : fn(), ptr(nullptr) {} + +utility::Cleanup::~Cleanup() { + if (this->fn.has_value()) { + this->fn.value()(this->ptr); + } +} + +utility::Cleanup::Cleanup(Cleanup &&other) : fn(other.fn), ptr(other.ptr) { + other.fn = std::nullopt; + other.ptr = nullptr; +} + +utility::Cleanup &utility::Cleanup::operator=(utility::Cleanup &&other) { + if (this->fn.has_value()) { + this->fn.value()(this->ptr); + } + + this->fn = other.fn; + this->ptr = other.ptr; + + other.fn = std::nullopt; + other.ptr = nullptr; + + return *this; +} diff --git a/src/utility.hpp b/src/utility.hpp index 6da17d9..fe152bd 100644 --- a/src/utility.hpp +++ b/src/utility.hpp @@ -3,6 +3,7 @@ #include #include +#include #include namespace utility { @@ -32,19 +33,22 @@ inline float dist(int a, int b, int width) { class Cleanup { public: + struct Nop {}; + Cleanup(std::function fn, void *ptr); + Cleanup(Nop nop); ~Cleanup(); // allow move - Cleanup(Cleanup &&) = default; - Cleanup &operator=(Cleanup &&) = default; + Cleanup(Cleanup &&); + Cleanup &operator=(Cleanup &&); // deny copy Cleanup(const Cleanup &) = delete; Cleanup &operator=(const Cleanup &) = delete; private: - std::function fn; + std::optional> fn; void *ptr; }; } // namespace utility