Compare commits

..

7 commits

Author SHA1 Message Date
Stephen Seo bd7afeb8bd Vulkan compute: move buffer init to before fn call 2024-04-01 12:50:54 +09:00
Stephen Seo 320a33842b Vulkan compute: resize max/min out buffers
Change max/min out buffers to have same size as max/min in buffers.
2024-04-01 12:50:54 +09:00
Stephen Seo 2abf3de665 Vulkan compute: minor refactoring 2024-04-01 12:50:54 +09:00
Stephen Seo 11de490e94 Vulkan compute: combine all minmax calls
This commit combines the minmax execution via Vulkan compute. The
previous implementation executed compute in vulkan_minmax with a new
command buffer each time. This implementation combines all required
executions of compute in vulkan_minmax in a single command buffer and
uses a pipeline to ensure the enqueued compute calls stay in order.
2024-04-01 12:50:54 +09:00
Stephen Seo 7bcb385625 Do "minmax" on Vulkan compute
Was an attempt to speed up blue-noise-generation with Vulkan compute,
but this implementation seems to slow it down instead.
2024-04-01 12:50:54 +09:00
Stephen Seo ff36314092 Update README.md 2024-04-01 11:30:42 +09:00
Stephen Seo 2854aa5104 Make OpenCL default backend
Order of backends to use:
OpenCL -> Vulkan -> CPU threads

Unless I figure out a way to make Vulkan faster, OpenCL will be the
default backend used, or at least it will have higher priority than
Vulkan if both OpenCL and Vulkan is available.
2024-04-01 11:19:55 +09:00
2 changed files with 91 additions and 90 deletions

View file

@ -1,4 +1,5 @@
# Blue_Noise_Generation
Currently, this project only generates blue-noise, which can be used for dithering.
The blue-noise can be generated via OpenCL or with threads on the CPU.
The blue-noise can be generated via OpenCL, Vulkan compute, or with threads on
the CPU.

View file

@ -794,6 +794,95 @@ std::optional<std::pair<int, int>> dither::internal::vulkan_minmax(
image::Bl dither::blue_noise(int width, int height, int threads,
bool use_opencl, bool use_vulkan) {
#if DITHERING_OPENCL_ENABLED == 1
if (use_opencl) {
// try to use OpenCL
do {
cl_device_id device;
cl_context context;
cl_program program;
cl_int err;
cl_platform_id platform;
int filter_size = (width + height) / 2;
err = clGetPlatformIDs(1, &platform, nullptr);
if (err != CL_SUCCESS) {
std::cerr << "OpenCL: Failed to identify a platform\n";
break;
}
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr);
if (err != CL_SUCCESS) {
std::cerr << "OpenCL: Failed to get a device\n";
break;
}
context = clCreateContext(nullptr, 1, &device, nullptr, nullptr, &err);
{
char buf[1024];
std::ifstream program_file("src/blue_noise.cl");
if (!program_file.good()) {
std::cerr << "ERROR: Failed to read \"src/blue_noise.cl\" "
"(not found?)\n";
break;
}
std::string program_string;
while (program_file.good()) {
program_file.read(buf, 1024);
if (int read_count = program_file.gcount(); read_count > 0) {
program_string.append(buf, read_count);
}
}
const char *string_ptr = program_string.c_str();
std::size_t program_size = program_string.size();
program = clCreateProgramWithSource(
context, 1, (const char **)&string_ptr, &program_size, &err);
if (err != CL_SUCCESS) {
std::cerr << "OpenCL: Failed to create the program\n";
clReleaseContext(context);
break;
}
err = clBuildProgram(program, 1, &device, nullptr, nullptr, nullptr);
if (err != CL_SUCCESS) {
std::cerr << "OpenCL: Failed to build the program\n";
std::size_t log_size;
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0,
nullptr, &log_size);
std::unique_ptr<char[]> log = std::make_unique<char[]>(log_size + 1);
log[log_size] = 0;
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size,
log.get(), nullptr);
std::cerr << log.get() << std::endl;
clReleaseProgram(program);
clReleaseContext(context);
break;
}
}
std::cout << "OpenCL: Initialized, trying cl_impl..." << std::endl;
std::vector<unsigned int> result = internal::blue_noise_cl_impl(
width, height, filter_size, context, device, program);
clReleaseProgram(program);
clReleaseContext(context);
if (!result.empty()) {
return internal::rangeToBl(result, width);
}
std::cout << "ERROR: Empty result\n";
} while (false);
}
#else
std::clog << "WARNING: Not compiled with OpenCL support!\n";
#endif
#if DITHERING_VULKAN_ENABLED == 1
if (use_vulkan) {
// Try to use Vulkan.
@ -1986,95 +2075,6 @@ ENDOF_VULKAN:
std::clog << "WARNING: Not compiled with Vulkan support!\n";
#endif // DITHERING_VULKAN_ENABLED == 1
#if DITHERING_OPENCL_ENABLED == 1
if (use_opencl) {
// try to use OpenCL
do {
cl_device_id device;
cl_context context;
cl_program program;
cl_int err;
cl_platform_id platform;
int filter_size = (width + height) / 2;
err = clGetPlatformIDs(1, &platform, nullptr);
if (err != CL_SUCCESS) {
std::cerr << "OpenCL: Failed to identify a platform\n";
break;
}
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr);
if (err != CL_SUCCESS) {
std::cerr << "OpenCL: Failed to get a device\n";
break;
}
context = clCreateContext(nullptr, 1, &device, nullptr, nullptr, &err);
{
char buf[1024];
std::ifstream program_file("src/blue_noise.cl");
if (!program_file.good()) {
std::cerr << "ERROR: Failed to read \"src/blue_noise.cl\" "
"(not found?)\n";
break;
}
std::string program_string;
while (program_file.good()) {
program_file.read(buf, 1024);
if (int read_count = program_file.gcount(); read_count > 0) {
program_string.append(buf, read_count);
}
}
const char *string_ptr = program_string.c_str();
std::size_t program_size = program_string.size();
program = clCreateProgramWithSource(
context, 1, (const char **)&string_ptr, &program_size, &err);
if (err != CL_SUCCESS) {
std::cerr << "OpenCL: Failed to create the program\n";
clReleaseContext(context);
break;
}
err = clBuildProgram(program, 1, &device, nullptr, nullptr, nullptr);
if (err != CL_SUCCESS) {
std::cerr << "OpenCL: Failed to build the program\n";
std::size_t log_size;
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0,
nullptr, &log_size);
std::unique_ptr<char[]> log = std::make_unique<char[]>(log_size + 1);
log[log_size] = 0;
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size,
log.get(), nullptr);
std::cerr << log.get() << std::endl;
clReleaseProgram(program);
clReleaseContext(context);
break;
}
}
std::cout << "OpenCL: Initialized, trying cl_impl..." << std::endl;
std::vector<unsigned int> result = internal::blue_noise_cl_impl(
width, height, filter_size, context, device, program);
clReleaseProgram(program);
clReleaseContext(context);
if (!result.empty()) {
return internal::rangeToBl(result, width);
}
std::cout << "ERROR: Empty result\n";
} while (false);
}
#else
std::clog << "WARNING: Not compiled with OpenCL support!\n";
#endif
std::cout << "Vulkan/OpenCL: Failed to setup/use or is not enabled, using "
"regular impl..."
<< std::endl;