Begin work on Vulkan compute (WIP)
Some Vulkan initialization stuff WIP.
This commit is contained in:
parent
0da27b59be
commit
4e4ee7f558
8 changed files with 212 additions and 16 deletions
|
@ -6,6 +6,7 @@ set(blueNoiseGen_SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/image.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/image.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/arg_parse.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/arg_parse.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/utility.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_compile_options(
|
add_compile_options(
|
||||||
|
@ -29,29 +30,48 @@ if(NOT DEFINED DISABLE_OPENCL OR NOT DISABLE_OPENCL)
|
||||||
else()
|
else()
|
||||||
message(STATUS "Not checking for OpenCL")
|
message(STATUS "Not checking for OpenCL")
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT DEFINED DISABLE_VULKAN OR NOT DISABLE_VULKAN)
|
||||||
|
find_package(Vulkan)
|
||||||
|
if(NOT DEFINED Vulkan_FOUND)
|
||||||
|
set(DISABLE_VULKAN True)
|
||||||
|
message(WARNING "Vulkan not found, Vulkan usage is disabled.")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "Not checking for Vulkan")
|
||||||
|
endif()
|
||||||
find_package(PNG REQUIRED)
|
find_package(PNG REQUIRED)
|
||||||
|
|
||||||
add_executable(blueNoiseGen ${blueNoiseGen_SOURCES})
|
add_executable(blueNoiseGen ${blueNoiseGen_SOURCES})
|
||||||
target_compile_features(blueNoiseGen PUBLIC cxx_std_17)
|
target_compile_features(blueNoiseGen PUBLIC cxx_std_17)
|
||||||
target_compile_definitions(blueNoiseGen PRIVATE CL_TARGET_OPENCL_VERSION=300)
|
target_compile_definitions(blueNoiseGen PRIVATE CL_TARGET_OPENCL_VERSION=300)
|
||||||
|
target_include_directories(blueNoiseGen PUBLIC Threads::Threads ${PNG_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(blueNoiseGen PUBLIC Threads::Threads ${PNG_LIBRARIES})
|
||||||
|
|
||||||
if(DEFINED DISABLE_OPENCL AND DISABLE_OPENCL)
|
if(DEFINED DISABLE_OPENCL AND DISABLE_OPENCL)
|
||||||
message(STATUS "OpenCL usage is disabled.")
|
message(STATUS "OpenCL usage is disabled.")
|
||||||
target_include_directories(blueNoiseGen PUBLIC
|
|
||||||
Threads::Threads
|
|
||||||
${PNG_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(blueNoiseGen PUBLIC
|
|
||||||
Threads::Threads
|
|
||||||
${PNG_LIBRARIES})
|
|
||||||
target_compile_definitions(blueNoiseGen PRIVATE DITHERING_OPENCL_ENABLED=0)
|
target_compile_definitions(blueNoiseGen PRIVATE DITHERING_OPENCL_ENABLED=0)
|
||||||
else()
|
else()
|
||||||
message(STATUS "OpenCL usage is enabled.")
|
message(STATUS "OpenCL usage is enabled.")
|
||||||
target_include_directories(blueNoiseGen PUBLIC
|
target_include_directories(blueNoiseGen PUBLIC
|
||||||
Threads::Threads
|
${OpenCL_INCLUDE_DIRS})
|
||||||
${OpenCL_INCLUDE_DIRS}
|
|
||||||
${PNG_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(blueNoiseGen PUBLIC
|
target_link_libraries(blueNoiseGen PUBLIC
|
||||||
Threads::Threads
|
${OpenCL_LIBRARIES})
|
||||||
${OpenCL_LIBRARIES}
|
|
||||||
${PNG_LIBRARIES})
|
|
||||||
target_compile_definitions(blueNoiseGen PRIVATE DITHERING_OPENCL_ENABLED=1)
|
target_compile_definitions(blueNoiseGen PRIVATE DITHERING_OPENCL_ENABLED=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED DISABLE_VULKAN AND DISABLE_VULKAN)
|
||||||
|
message(STATUS "Vulkan usage is disabled.")
|
||||||
|
target_compile_definitions(blueNoiseGen PRIVATE DITHERING_VULKAN_ENABLED=0)
|
||||||
|
else()
|
||||||
|
message(STATUS "Vulkan usage is enabled.")
|
||||||
|
target_include_directories(blueNoiseGen PUBLIC
|
||||||
|
${Vulkan_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(blueNoiseGen PUBLIC
|
||||||
|
${Vulkan_LIBRARIES})
|
||||||
|
target_compile_definitions(blueNoiseGen PRIVATE DITHERING_VULKAN_ENABLED=1)
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
|
target_compile_definitions(blueNoiseGen PRIVATE VULKAN_VALIDATION=1)
|
||||||
|
else()
|
||||||
|
target_compile_definitions(blueNoiseGen PRIVATE VULKAN_VALIDATION=0)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
|
@ -7,6 +7,7 @@ Args::Args()
|
||||||
: generate_blue_noise_(false),
|
: generate_blue_noise_(false),
|
||||||
use_opencl_(true),
|
use_opencl_(true),
|
||||||
overwrite_file_(false),
|
overwrite_file_(false),
|
||||||
|
use_vulkan_(true),
|
||||||
blue_noise_size_(32),
|
blue_noise_size_(32),
|
||||||
threads_(4),
|
threads_(4),
|
||||||
output_filename_("output.png") {}
|
output_filename_("output.png") {}
|
||||||
|
@ -26,7 +27,9 @@ void Args::DisplayHelp() {
|
||||||
" -o <filelname> | --output <filename>\tOutput filename to "
|
" -o <filelname> | --output <filename>\tOutput filename to "
|
||||||
"use\n"
|
"use\n"
|
||||||
" --overwrite\t\t\t\tEnable overwriting of file (default "
|
" --overwrite\t\t\t\tEnable overwriting of file (default "
|
||||||
"disabled)\n";
|
"disabled)\n"
|
||||||
|
" --usevulkan | --nousevulkan\t\t\tUse/Disable Vulkan (enabled "
|
||||||
|
"by default)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Args::ParseArgs(int argc, char **argv) {
|
bool Args::ParseArgs(int argc, char **argv) {
|
||||||
|
@ -69,6 +72,10 @@ bool Args::ParseArgs(int argc, char **argv) {
|
||||||
output_filename_ = std::string(argv[1]);
|
output_filename_ = std::string(argv[1]);
|
||||||
--argc;
|
--argc;
|
||||||
++argv;
|
++argv;
|
||||||
|
} else if (std::strcmp(argv[0], "--usevulkan") == 0) {
|
||||||
|
use_vulkan_ = true;
|
||||||
|
} else if (std::strcmp(argv[0], "--nousevulkan") == 0) {
|
||||||
|
use_vulkan_ = false;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "WARNING: Ignoring invalid input \"" << argv[0] << "\""
|
std::cout << "WARNING: Ignoring invalid input \"" << argv[0] << "\""
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
|
@ -14,6 +14,7 @@ struct Args {
|
||||||
bool generate_blue_noise_;
|
bool generate_blue_noise_;
|
||||||
bool use_opencl_;
|
bool use_opencl_;
|
||||||
bool overwrite_file_;
|
bool overwrite_file_;
|
||||||
|
bool use_vulkan_;
|
||||||
unsigned int blue_noise_size_;
|
unsigned int blue_noise_size_;
|
||||||
unsigned int threads_;
|
unsigned int threads_;
|
||||||
std::string output_filename_;
|
std::string output_filename_;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -13,11 +14,153 @@
|
||||||
#include <CL/opencl.h>
|
#include <CL/opencl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if DITHERING_VULKAN_ENABLED == 1
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
static std::vector<const char *> VK_EXTENSIONS = {};
|
||||||
|
|
||||||
|
#if VULKAN_VALIDATION == 1
|
||||||
|
const std::vector<const char *> VALIDATION_LAYERS = {
|
||||||
|
"VK_LAYER_KHRONOS_validation"};
|
||||||
|
|
||||||
|
static VKAPI_ATTR VkBool32 VKAPI_CALL fn_VULKAN_DEBUG_CALLBACK(
|
||||||
|
VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT,
|
||||||
|
const VkDebugUtilsMessengerCallbackDataEXT *p_callback_data, void *) {
|
||||||
|
std::cerr << "Validation layer: " << p_callback_data->pMessage << std::endl;
|
||||||
|
|
||||||
|
return VK_FALSE;
|
||||||
|
}
|
||||||
|
#endif // VULKAN_VALIDATION == 1
|
||||||
|
#endif // DITHERING_VULKAN_ENABLED == 1
|
||||||
|
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
|
|
||||||
image::Bl dither::blue_noise(int width, int height, int threads,
|
image::Bl dither::blue_noise(int width, int height, int threads,
|
||||||
bool use_opencl) {
|
bool use_opencl, bool use_vulkan) {
|
||||||
bool using_opencl = false;
|
bool using_opencl = false;
|
||||||
|
bool using_vulkan = false;
|
||||||
|
|
||||||
|
#if DITHERING_VULKAN_ENABLED == 1
|
||||||
|
if (use_vulkan) {
|
||||||
|
// Try to use Vulkan.
|
||||||
|
#if VULKAN_VALIDATION == 1
|
||||||
|
// Check for validation support.
|
||||||
|
uint32_t layer_count;
|
||||||
|
vkEnumerateInstanceLayerProperties(&layer_count, nullptr);
|
||||||
|
|
||||||
|
std::vector<VkLayerProperties> available_layers(layer_count);
|
||||||
|
vkEnumerateInstanceLayerProperties(&layer_count, available_layers.data());
|
||||||
|
|
||||||
|
bool validation_supported = true;
|
||||||
|
|
||||||
|
for (const char *layer_name : VALIDATION_LAYERS) {
|
||||||
|
bool layer_found = false;
|
||||||
|
|
||||||
|
for (const auto &layer_props : available_layers) {
|
||||||
|
if (std::strcmp(layer_name, layer_props.layerName) == 0) {
|
||||||
|
layer_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!layer_found) {
|
||||||
|
validation_supported = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validation_supported) {
|
||||||
|
std::clog << "WARNING: Validation requested but not supported, cannot "
|
||||||
|
"use Vulkan!\n";
|
||||||
|
goto ENDOF_VULKAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
VK_EXTENSIONS.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
|
#endif // VULKAN_VALIDATION == 1
|
||||||
|
|
||||||
|
VkApplicationInfo app_info{};
|
||||||
|
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
|
app_info.pApplicationName = "Blue Noise Generation";
|
||||||
|
app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||||
|
app_info.pEngineName = "No Engine";
|
||||||
|
app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||||
|
app_info.apiVersion = VK_API_VERSION_1_0;
|
||||||
|
|
||||||
|
VkInstanceCreateInfo create_info{};
|
||||||
|
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
create_info.pApplicationInfo = &app_info;
|
||||||
|
|
||||||
|
create_info.enabledExtensionCount = VK_EXTENSIONS.size();
|
||||||
|
create_info.ppEnabledExtensionNames = VK_EXTENSIONS.data();
|
||||||
|
|
||||||
|
VkDebugUtilsMessengerCreateInfoEXT debug_create_info{};
|
||||||
|
#if VULKAN_VALIDATION == 1
|
||||||
|
create_info.enabledLayerCount = VALIDATION_LAYERS.size();
|
||||||
|
create_info.ppEnabledLayerNames = VALIDATION_LAYERS.data();
|
||||||
|
|
||||||
|
const auto populate_debug_info =
|
||||||
|
[](VkDebugUtilsMessengerCreateInfoEXT *info) {
|
||||||
|
info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||||
|
info->messageSeverity =
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
|
info->messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
|
info->pfnUserCallback = fn_VULKAN_DEBUG_CALLBACK;
|
||||||
|
};
|
||||||
|
|
||||||
|
populate_debug_info(&debug_create_info);
|
||||||
|
|
||||||
|
create_info.pNext = &debug_create_info;
|
||||||
|
|
||||||
|
create_info.enabledExtensionCount = 1;
|
||||||
|
#else
|
||||||
|
create_info.enabledLayerCount = 0;
|
||||||
|
create_info.pNext = nullptr;
|
||||||
|
#endif // VULKAN_VALIDATION == 1
|
||||||
|
|
||||||
|
VkInstance instance;
|
||||||
|
if (vkCreateInstance(&create_info, nullptr, &instance) != VK_SUCCESS) {
|
||||||
|
std::clog << "WARNING: Failed to create Vulkan instance!\n";
|
||||||
|
goto ENDOF_VULKAN;
|
||||||
|
}
|
||||||
|
utility::Cleanup cleanup_vk_instance(
|
||||||
|
[](void *ptr) { vkDestroyInstance(*((VkInstance *)ptr), nullptr); },
|
||||||
|
&instance);
|
||||||
|
|
||||||
|
#if VULKAN_VALIDATION == 1
|
||||||
|
populate_debug_info(&debug_create_info);
|
||||||
|
VkDebugUtilsMessengerEXT debug_messenger;
|
||||||
|
|
||||||
|
auto create_debug_utils_messenger_func =
|
||||||
|
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
||||||
|
instance, "vkCreateDebugUtilsMessengerEXT");
|
||||||
|
if (create_debug_utils_messenger_func != nullptr &&
|
||||||
|
create_debug_utils_messenger_func(instance, &debug_create_info, nullptr,
|
||||||
|
&debug_messenger) != VK_SUCCESS) {
|
||||||
|
std::clog << "WARNING: Failed to set up Vulkan debug messenger!\n";
|
||||||
|
goto ENDOF_VULKAN;
|
||||||
|
}
|
||||||
|
utility::Cleanup cleanup_debug_messenger(
|
||||||
|
[instance](void *ptr) {
|
||||||
|
auto func =
|
||||||
|
(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
||||||
|
instance, "vkDestroyDebugUtilsMessengerEXT");
|
||||||
|
if (func != nullptr) {
|
||||||
|
func(instance, *((VkDebugUtilsMessengerEXT *)ptr), nullptr);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&debug_messenger);
|
||||||
|
#endif // VULKAN_VALIDATION == 1
|
||||||
|
}
|
||||||
|
ENDOF_VULKAN:
|
||||||
|
std::clog << "TODO: Remove this once Vulkan support is implemented.\n";
|
||||||
|
return {};
|
||||||
|
#else
|
||||||
|
std::clog << "WARNING: Not compiled with Vulkan support!\n";
|
||||||
|
#endif // DITHERING_VULKAN_ENABLED == 1
|
||||||
|
|
||||||
#if DITHERING_OPENCL_ENABLED == 1
|
#if DITHERING_OPENCL_ENABLED == 1
|
||||||
if (use_opencl) {
|
if (use_opencl) {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
namespace dither {
|
namespace dither {
|
||||||
|
|
||||||
image::Bl blue_noise(int width, int height, int threads = 1,
|
image::Bl blue_noise(int width, int height, int threads = 1,
|
||||||
bool use_opencl = true);
|
bool use_opencl = true, bool use_vulkan = true);
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
std::vector<unsigned int> blue_noise_impl(int width, int height,
|
std::vector<unsigned int> blue_noise_impl(int width, int height,
|
||||||
|
|
|
@ -41,7 +41,7 @@ int main(int argc, char **argv) {
|
||||||
std::cout << "Generating blue_noise..." << std::endl;
|
std::cout << "Generating blue_noise..." << std::endl;
|
||||||
image::Bl bl =
|
image::Bl bl =
|
||||||
dither::blue_noise(args.blue_noise_size_, args.blue_noise_size_,
|
dither::blue_noise(args.blue_noise_size_, args.blue_noise_size_,
|
||||||
args.threads_, args.use_opencl_);
|
args.threads_, args.use_opencl_, args.use_vulkan_);
|
||||||
if (!bl.writeToFile(image::file_type::PNG, args.overwrite_file_,
|
if (!bl.writeToFile(image::file_type::PNG, args.overwrite_file_,
|
||||||
args.output_filename_)) {
|
args.output_filename_)) {
|
||||||
std::cout << "ERROR: Failed to write blue-noise to file\n";
|
std::cout << "ERROR: Failed to write blue-noise to file\n";
|
||||||
|
|
6
src/utility.cpp
Normal file
6
src/utility.cpp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
utility::Cleanup::Cleanup(std::function<void(void *)> fn, void *ptr)
|
||||||
|
: fn(fn), ptr(ptr) {}
|
||||||
|
|
||||||
|
utility::Cleanup::~Cleanup() { this->fn(this->ptr); }
|
|
@ -2,6 +2,7 @@
|
||||||
#define DITHERING_UTILITY_HPP
|
#define DITHERING_UTILITY_HPP
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <functional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace utility {
|
namespace utility {
|
||||||
|
@ -28,6 +29,24 @@ inline float dist(int a, int b, int width) {
|
||||||
float dy = axy.second - bxy.second;
|
float dy = axy.second - bxy.second;
|
||||||
return std::sqrt(dx * dx + dy * dy);
|
return std::sqrt(dx * dx + dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Cleanup {
|
||||||
|
public:
|
||||||
|
Cleanup(std::function<void(void *)> fn, void *ptr);
|
||||||
|
~Cleanup();
|
||||||
|
|
||||||
|
// allow move
|
||||||
|
Cleanup(Cleanup &&) = default;
|
||||||
|
Cleanup &operator=(Cleanup &&) = default;
|
||||||
|
|
||||||
|
// deny copy
|
||||||
|
Cleanup(const Cleanup &) = delete;
|
||||||
|
Cleanup &operator=(const Cleanup &) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::function<void(void *)> fn;
|
||||||
|
void *ptr;
|
||||||
|
};
|
||||||
} // namespace utility
|
} // namespace utility
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue