Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
bb4140b819 | |||
8e66150aae | |||
e3e544214a | |||
4ec9195857 | |||
c8fda11c5c | |||
fc0de0aa30 | |||
49201ea8cf | |||
4d26053a70 | |||
b04b8c2fcf | |||
2b08a61fed | |||
173d18acec |
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
[submodule "cglm/cglm"]
|
||||
path = cglm/cglm
|
||||
url = https://github.com/recp/cglm
|
||||
branch = master
|
@ -1,22 +1,37 @@
|
||||
project(mandelbrot)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_search_module(GLIB REQUIRED glib-2.0)
|
||||
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
||||
pkg_check_modules(CAIRO REQUIRED cairo)
|
||||
|
||||
add_subdirectory(glade)
|
||||
find_package(OpenCL REQUIRED)
|
||||
|
||||
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS})
|
||||
|
||||
|
||||
add_subdirectory(glade)
|
||||
add_subdirectory(cglm)
|
||||
|
||||
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS} ${OPENCL_INCLUDE_DIRS})
|
||||
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
|
||||
add_definitions(${GLIB2_CFLAGS_OTHER})
|
||||
|
||||
configure_file("mandelbrot.cl" "cl_kernels/mandelbrot.cl" COPYONLY)
|
||||
|
||||
aux_source_directory("src" SOURCES)
|
||||
add_compile_options(-Wall)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c)
|
||||
add_dependencies(${PROJECT_NAME} glib-resources)
|
||||
add_dependencies(${PROJECT_NAME} glib-resources cglm)
|
||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/glade/resources.c PROPERTIES GENERATED 1)
|
||||
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m pthread)
|
||||
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${CAIRO_LDFLAGS} m pthread ${OPENCL_LIBRARIES} epoxy cglm)
|
||||
install (TARGETS ${PROJECT_NAME} DESTINATION bin)
|
||||
|
||||
message(STATUS "OpenCL found: ${OPENCL_FOUND}")
|
||||
message(STATUS "OpenCL includes: ${OPENCL_INCLUDE_DIRS}")
|
||||
message(STATUS "OpenCL CXX includes: ${OPENCL_HAS_CPP_BINDINGS}")
|
||||
message(STATUS "OpenCL libraries: ${OPENCL_LIBRARIES}")
|
||||
|
14
cglm/CMakeLists.txt
Normal file
14
cglm/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
project(cglm)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
include_directories(${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS} ${OPENCL_INCLUDE_DIRS})
|
||||
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${CAIRO_LINK_DIRS})
|
||||
add_definitions(${GLIB2_CFLAGS_OTHER})
|
||||
|
||||
aux_source_directory("cglm/src" SOURCES)
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||
add_compile_options(-Wall -std=gnu99 -O3 -Wstrict-aliasing=2 -fstrict-aliasing -pedantic)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC "cglm/include")
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} m)
|
||||
|
1
cglm/cglm
Submodule
1
cglm/cglm
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 7cdeada70129c08f40ca89b523e71b4428b55029
|
171
cmake/FindOpenCL.cmake
Normal file
171
cmake/FindOpenCL.cmake
Normal file
@ -0,0 +1,171 @@
|
||||
# Find OpenCL
|
||||
#
|
||||
# To set manually the paths, define these environment variables:
|
||||
# OpenCL_INCPATH - Include path (e.g. OpenCL_INCPATH=/opt/cuda/4.0/cuda/include)
|
||||
# OpenCL_LIBPATH - Library path (e.h. OpenCL_LIBPATH=/usr/lib64/nvidia)
|
||||
#
|
||||
# Once done this will define
|
||||
# OPENCL_FOUND - system has OpenCL
|
||||
# OPENCL_INCLUDE_DIRS - the OpenCL include directory
|
||||
# OPENCL_LIBRARIES - link these to use OpenCL
|
||||
# OPENCL_HAS_CPP_BINDINGS - system has also cl.hpp
|
||||
|
||||
FIND_PACKAGE(PackageHandleStandardArgs)
|
||||
|
||||
SET (OPENCL_VERSION_STRING "0.1.0")
|
||||
SET (OPENCL_VERSION_MAJOR 0)
|
||||
SET (OPENCL_VERSION_MINOR 1)
|
||||
SET (OPENCL_VERSION_PATCH 0)
|
||||
|
||||
IF (APPLE)
|
||||
|
||||
# IF OpenCL_LIBPATH is given use it and don't use default path
|
||||
IF (DEFINED ENV{OpenCL_LIBPATH})
|
||||
FIND_LIBRARY(OPENCL_LIBRARIES OpenCL PATHS ENV OpenCL_LIBPATH NO_DEFAULT_PATH)
|
||||
ELSE ()
|
||||
FIND_LIBRARY(OPENCL_LIBRARIES OpenCL DOC "OpenCL lib for OSX")
|
||||
ENDIF ()
|
||||
|
||||
# IF OpenCL_INCPATH is given use it and find for CL/cl.h and OpenCL/cl.h do not try to find default paths
|
||||
IF (DEFINED ENV{OpenCL_INCPATH})
|
||||
FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h OpenCL/cl.h PATHS ENV OpenCL_INCPATH NO_DEFAULT_PATH)
|
||||
FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp OpenCL/cl.hpp PATHS ${OPENCL_INCLUDE_DIRS} NO_DEFAULT_PATH)
|
||||
ELSE ()
|
||||
FIND_PATH(OPENCL_INCLUDE_DIRS OpenCL/cl.h DOC "Include for OpenCL on OSX")
|
||||
FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS OpenCL/cl.hpp DOC "Include for OpenCL CPP bindings on OSX")
|
||||
ENDIF ()
|
||||
|
||||
ELSE (APPLE)
|
||||
|
||||
IF (WIN32)
|
||||
|
||||
# Find OpenCL includes and libraries from environment variables provided by vendor
|
||||
SET(OPENCL_INCLUDE_SEARCH_PATHS)
|
||||
SET(OPENCL_LIBRARY_SEARCH_PATHS)
|
||||
SET(OPENCL_LIBRARY_64_SEARCH_PATHS)
|
||||
|
||||
# Nvidia
|
||||
IF (DEFINED ENV{CUDA_INC_PATH})
|
||||
SET(OPENCL_INCLUDE_SEARCH_PATHS ${OPENCL_INCLUDE_SEARCH_PATHS} $ENV{CUDA_INC_PATH})
|
||||
SET(OPENCL_LIBRARY_64_SEARCH_PATHS ${OPENCL_LIBRARY_64_SEARCH_PATHS} $ENV{CUDA_LIB_PATH}/../lib64)
|
||||
SET(OPENCL_LIBRARY_SEARCH_PATHS ${OPENCL_LIBRARY_SEARCH_PATHS} $ENV{CUDA_LIB_PATH}/../lib)
|
||||
ENDIF()
|
||||
IF (DEFINED ENV{CUDA_PATH})
|
||||
SET(OPENCL_INCLUDE_SEARCH_PATHS ${OPENCL_INCLUDE_SEARCH_PATHS} $ENV{CUDA_INC_PATH})
|
||||
SET(OPENCL_LIBRARY_64_SEARCH_PATHS ${OPENCL_LIBRARY_64_SEARCH_PATHS} $ENV{CUDA_PATH}/lib/x64/)
|
||||
SET(OPENCL_LIBRARY_SEARCH_PATHS ${OPENCL_LIBRARY_SEARCH_PATHS} $ENV{CUDA_PATH}/lib/Win32/)
|
||||
ENDIF()
|
||||
|
||||
# Intel SDK
|
||||
IF (DEFINED ENV{INTELOCSDKROOT})
|
||||
SET(OPENCL_INCLUDE_SEARCH_PATHS ${OPENCL_INCLUDE_SEARCH_PATHS} $ENV{INTELOCSDKROOT}/include)
|
||||
SET(OPENCL_LIBRARY_64_SEARCH_PATHS ${OPENCL_LIBRARY_64_SEARCH_PATHS} $ENV{INTELOCSDKROOT}/lib/x64)
|
||||
SET(OPENCL_LIBRARY_SEARCH_PATHS ${OPENCL_LIBRARY_SEARCH_PATHS} $ENV{INTELOCSDKROOT}/lib/x86)
|
||||
ENDIF()
|
||||
|
||||
# AMD SDK
|
||||
IF (DEFINED ENV{AMDAPPSDKROOT})
|
||||
SET(OPENCL_INCLUDE_SEARCH_PATHS ${OPENCL_INCLUDE_SEARCH_PATHS} $ENV{AMDAPPSDKROOT}/include)
|
||||
SET(OPENCL_LIBRARY_64_SEARCH_PATHS ${OPENCL_LIBRARY_64_SEARCH_PATHS} $ENV{AMDAPPSDKROOT}/lib/x86_64)
|
||||
SET(OPENCL_LIBRARY_SEARCH_PATHS ${OPENCL_LIBRARY_SEARCH_PATHS} $ENV{AMDAPPSDKROOT}/lib/x86)
|
||||
ENDIF()
|
||||
|
||||
# Override search paths with OpenCL_INCPATH env variable
|
||||
IF (DEFINED ENV{OpenCL_INCPATH})
|
||||
SET(OPENCL_INCLUDE_SEARCH_PATHS $ENV{OpenCL_INCPATH})
|
||||
ENDIF ()
|
||||
|
||||
# Override search paths with OpenCL_LIBPATH env variable
|
||||
IF (DEFINED ENV{OpenCL_LIBPATH})
|
||||
SET(OPENCL_LIBRARY_SEARCH_PATHS $ENV{OpenCL_LIBPATH})
|
||||
SET(OPENCL_LIBRARY_64_SEARCH_PATHS $ENV{OpenCL_LIBPATH})
|
||||
ENDIF ()
|
||||
|
||||
FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS ${OPENCL_INCLUDE_SEARCH_PATHS})
|
||||
FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS ${OPENCL_INCLUDE_SEARCH_PATHS})
|
||||
|
||||
FIND_LIBRARY(_OPENCL_32_LIBRARIES OpenCL.lib HINTS ${OPENCL_LIBRARY_SEARCH_PATHS} PATHS ${OPENCL_LIB_DIR} ENV PATH)
|
||||
FIND_LIBRARY(_OPENCL_64_LIBRARIES OpenCL.lib HINTS ${OPENCL_LIBRARY_64_SEARCH_PATHS} PATHS ${OPENCL_LIB_DIR} ENV PATH)
|
||||
|
||||
# Check if 64bit or 32bit versions links fine
|
||||
SET (_OPENCL_VERSION_SOURCE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/openclversion.c")
|
||||
#SET (_OPENCL_VERSION_SOURCE "${CMAKE_BINARY_DIR}/test.c")
|
||||
FILE (WRITE "${_OPENCL_VERSION_SOURCE}"
|
||||
"
|
||||
#if __APPLE__
|
||||
#include <OpenCL/cl.h>
|
||||
#else /* !__APPLE__ */
|
||||
#include <CL/cl.h>
|
||||
#endif /* __APPLE__ */
|
||||
int main()
|
||||
{
|
||||
cl_int result;
|
||||
cl_platform_id id;
|
||||
result = clGetPlatformIDs(1, &id, NULL);
|
||||
return result != CL_SUCCESS;
|
||||
}
|
||||
")
|
||||
|
||||
TRY_COMPILE(_OPENCL_64_COMPILE_SUCCESS ${CMAKE_BINARY_DIR} "${_OPENCL_VERSION_SOURCE}"
|
||||
CMAKE_FLAGS
|
||||
"-DINCLUDE_DIRECTORIES:STRING=${OPENCL_INCLUDE_DIRS}"
|
||||
CMAKE_FLAGS
|
||||
"-DLINK_LIBRARIES:STRING=${_OPENCL_64_LIBRARIES}"
|
||||
)
|
||||
|
||||
IF(_OPENCL_64_COMPILE_SUCCESS)
|
||||
message(STATUS "OpenCL 64bit lib found.")
|
||||
SET(OPENCL_LIBRARIES ${_OPENCL_64_LIBRARIES})
|
||||
ELSE()
|
||||
TRY_COMPILE(_OPENCL_32_COMPILE_SUCCESS ${CMAKE_BINARY_DIR} "${_OPENCL_VERSION_SOURCE}"
|
||||
CMAKE_FLAGS
|
||||
"-DINCLUDE_DIRECTORIES:STRING=${OPENCL_INCLUDE_DIRS}"
|
||||
CMAKE_FLAGS
|
||||
"-DLINK_LIBRARIES:STRING=${_OPENCL_32_LIBRARIES}"
|
||||
)
|
||||
IF(_OPENCL_32_COMPILE_SUCCESS)
|
||||
message(STATUS "OpenCL 32bit lib found.")
|
||||
SET(OPENCL_LIBRARIES ${_OPENCL_32_LIBRARIES})
|
||||
ELSE()
|
||||
message(STATUS "Couldn't link opencl..")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
||||
ELSE (WIN32)
|
||||
|
||||
IF (CYGWIN)
|
||||
SET (CMAKE_FIND_LIBRARY_SUFFIXES .lib)
|
||||
SET (OCL_LIB_SUFFIX .lib)
|
||||
ENDIF (CYGWIN)
|
||||
|
||||
# Unix style platforms
|
||||
FIND_LIBRARY(OPENCL_LIBRARIES OpenCL${OCL_LIB_SUFFIX}
|
||||
PATHS ENV LD_LIBRARY_PATH ENV OpenCL_LIBPATH
|
||||
)
|
||||
|
||||
GET_FILENAME_COMPONENT(OPENCL_LIB_DIR ${OPENCL_LIBRARIES} PATH)
|
||||
GET_FILENAME_COMPONENT(_OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE)
|
||||
|
||||
# The AMD SDK currently does not place its headers
|
||||
# in /usr/include, therefore also search relative
|
||||
# to the library
|
||||
FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH)
|
||||
FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH)
|
||||
|
||||
ENDIF (WIN32)
|
||||
|
||||
ENDIF (APPLE)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenCL DEFAULT_MSG OPENCL_LIBRARIES OPENCL_INCLUDE_DIRS)
|
||||
|
||||
IF(_OPENCL_CPP_INCLUDE_DIRS)
|
||||
SET( OPENCL_HAS_CPP_BINDINGS TRUE )
|
||||
LIST( APPEND OPENCL_INCLUDE_DIRS ${_OPENCL_CPP_INCLUDE_DIRS} )
|
||||
# This is often the same, so clean up
|
||||
LIST( REMOVE_DUPLICATES OPENCL_INCLUDE_DIRS )
|
||||
ENDIF(_OPENCL_CPP_INCLUDE_DIRS)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
OPENCL_INCLUDE_DIRS
|
||||
)
|
@ -11,10 +11,7 @@
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDrawingArea" id="drawing-area">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
46
mandelbrot.cl
Normal file
46
mandelbrot.cl
Normal file
@ -0,0 +1,46 @@
|
||||
__kernel void mandelbrot(__global unsigned char *out_buff, unsigned int iter, double cx, double cy, double xs, double ys, unsigned int width, unsigned int height)
|
||||
{
|
||||
const int idx = get_global_id(0);
|
||||
|
||||
unsigned int i;
|
||||
double z_real, z_imag;
|
||||
double z2_real, z2_imag;
|
||||
double pt_real, pt_imag;
|
||||
double color_scale;
|
||||
unsigned int r, g, b;
|
||||
|
||||
const unsigned int pix_x = idx % width;
|
||||
const unsigned int pix_y = (unsigned int)idx / width;
|
||||
const double val_per_x_pixel = xs / (width - 1);
|
||||
const double val_per_y_pixel = ys / (height - 1);
|
||||
|
||||
|
||||
pt_real = (((double)pix_x - (double)(width - 1) / 2)) * val_per_x_pixel + cx;
|
||||
pt_imag = (((double)pix_y - (double)(height - 1) / 2)) * val_per_y_pixel + cy;
|
||||
|
||||
z_real = 0.0;
|
||||
z_imag = 0.0;
|
||||
|
||||
for (i = 0; i < iter; i++) {
|
||||
z2_real = z_real * z_real - z_imag * z_imag;
|
||||
z2_imag = 2.0 * z_real * z_imag;
|
||||
|
||||
z_real = z2_real + pt_real;
|
||||
z_imag = z2_imag + pt_imag;
|
||||
|
||||
if ((z_real * z_real + z_imag * z_imag) >= 4.0)
|
||||
break;
|
||||
}
|
||||
|
||||
color_scale = (double)(i) / (double)iter;
|
||||
if (i != iter) {
|
||||
r = (unsigned char)(255.0 * sqrt((1-color_scale)));
|
||||
g = (unsigned char)(255.0 * color_scale*color_scale);
|
||||
b = (unsigned char)(255.0 * color_scale);
|
||||
} else {
|
||||
r = g = b = 0;
|
||||
}
|
||||
out_buff[idx*3] = r;
|
||||
out_buff[idx*3+1] = g;
|
||||
out_buff[idx*3+2] = b;
|
||||
}
|
420
src/main.c
420
src/main.c
@ -1,17 +1,48 @@
|
||||
#include <stdio.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <math.h>
|
||||
#include <threads.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <CL/cl.h>
|
||||
#include <epoxy/gl.h>
|
||||
#include <epoxy/glx.h>
|
||||
#include <time.h>
|
||||
#include <cglm/call.h>
|
||||
|
||||
static const char * const vertex_shader = "#version 330 core\n \
|
||||
layout (location = 0) in vec3 aPos;\n \
|
||||
layout (location = 1) in vec2 aTexCoord;\n\
|
||||
out vec2 texCoord;\n\
|
||||
out vec3 vertPos;\n \
|
||||
uniform float zoom;\n\
|
||||
void main()\n \
|
||||
{\n \
|
||||
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n \
|
||||
texCoord = aTexCoord / zoom;\n\
|
||||
vertPos = aPos;\n\
|
||||
}\n";
|
||||
|
||||
static const char * const orange_framgment_shader = " \
|
||||
#version 330 core\n \
|
||||
out vec4 FragColor;\n \
|
||||
in vec3 vertPos;\n \
|
||||
in vec2 texCoord;\n \
|
||||
uniform sampler2D ourTexture;\n \
|
||||
\n \
|
||||
void main()\n \
|
||||
{\n \
|
||||
FragColor = texture(ourTexture, texCoord);\n\
|
||||
}";
|
||||
|
||||
struct canvas_buffer {
|
||||
unsigned int *mandelbrot_buffer;
|
||||
unsigned int iterations;
|
||||
unsigned int height;
|
||||
unsigned int width;
|
||||
double center_x;
|
||||
double center_y;
|
||||
double x_span;
|
||||
double y_span;
|
||||
unsigned char *mandelbrot_buffer;
|
||||
unsigned int iterations;
|
||||
unsigned int height;
|
||||
unsigned int width;
|
||||
double center_x;
|
||||
double center_y;
|
||||
double x_span;
|
||||
double y_span;
|
||||
};
|
||||
|
||||
static gboolean on_main_window_close(GtkWidget *window, gpointer data)
|
||||
@ -20,138 +51,337 @@ static gboolean on_main_window_close(GtkWidget *window, gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean drawing_callback(GtkWidget *widget, cairo_t *cr, gpointer data)
|
||||
void check_error(cl_int error)
|
||||
{
|
||||
struct canvas_buffer *buff = (struct canvas_buffer *)data;
|
||||
int width;
|
||||
int height;
|
||||
GtkStyleContext *style_context;
|
||||
int x, y;
|
||||
double color_scale;
|
||||
if (error != CL_SUCCESS) {
|
||||
printf("OpenCL call failed with error %d\n", (int)error);
|
||||
exit(error);
|
||||
}
|
||||
}
|
||||
|
||||
style_context = gtk_widget_get_style_context(widget);
|
||||
width = gtk_widget_get_allocated_width(widget);
|
||||
height = gtk_widget_get_allocated_height(widget);
|
||||
void load_kernel_from_file(char *file, char **src)
|
||||
{
|
||||
long fsize;
|
||||
FILE *f = fopen(file, "rb");
|
||||
|
||||
cairo_save(cr);
|
||||
/* Drawing code start */
|
||||
cairo_scale(cr, 1, -1);
|
||||
cairo_translate(cr, (double)width/2.0, -(double)height/2.0);
|
||||
fseek(f, 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET); //same as rewind(f);
|
||||
*src = (char *)malloc(fsize + 1);
|
||||
fread(*src, fsize, 1, f);
|
||||
fclose(f);
|
||||
(*src)[fsize] = 0;
|
||||
}
|
||||
|
||||
for (x = 0; x < buff->width; x++) {
|
||||
for (y = 0; y < buff->height; y++) {
|
||||
cairo_rectangle(cr,
|
||||
((double)x - (double)(buff->width - 1) / 2),
|
||||
((double)y - (double)(buff->height - 1) / 2),
|
||||
1,
|
||||
1);
|
||||
if (buff->mandelbrot_buffer[y * buff->width + x] == buff->iterations) {
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
} else {
|
||||
color_scale = (double)buff->mandelbrot_buffer[y * buff->width + x] / buff->iterations;
|
||||
cairo_set_source_rgb (cr, (sqrt(1-color_scale)), (color_scale*color_scale), color_scale);
|
||||
}
|
||||
cairo_fill(cr);
|
||||
cl_program create_program(char *src, cl_context context)
|
||||
{
|
||||
cl_program program;
|
||||
size_t lengths[1];
|
||||
cl_int error = 0;
|
||||
|
||||
}
|
||||
lengths[0] = strlen(src);
|
||||
printf("strlen: %u\n", (unsigned int)lengths[0]);
|
||||
program = clCreateProgramWithSource(context, 1, (const char **)&src,
|
||||
lengths, &error);
|
||||
check_error(error);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
static int calculate_mandelbrot(struct canvas_buffer *buff)
|
||||
{
|
||||
|
||||
int i;
|
||||
cl_int error;
|
||||
cl_int ret;
|
||||
cl_platform_id *platform_ids = NULL;
|
||||
cl_device_id *device_ids = NULL;
|
||||
cl_uint platform_id_count = 0;
|
||||
cl_uint device_id_count = 0;
|
||||
cl_context context;
|
||||
cl_program program;
|
||||
cl_kernel kernel;
|
||||
cl_command_queue queue;
|
||||
cl_mem dat_buff;
|
||||
char *source_code = NULL;
|
||||
char temp_buff[100];
|
||||
size_t data_size;
|
||||
size_t work_size = 64;
|
||||
|
||||
|
||||
data_size = buff->width*buff->height;
|
||||
|
||||
if (!buff->mandelbrot_buffer)
|
||||
buff->mandelbrot_buffer = (unsigned char *)malloc(data_size*3);
|
||||
|
||||
if (!buff->mandelbrot_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
clGetPlatformIDs(0, NULL, &platform_id_count);
|
||||
if (platform_id_count == 0)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_ids = (cl_platform_id *)malloc(platform_id_count *
|
||||
sizeof(cl_platform_id));
|
||||
if (platform_ids == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
clGetPlatformIDs(platform_id_count, platform_ids, NULL);
|
||||
|
||||
printf("Platforms available: %u\n", (unsigned int)platform_id_count);
|
||||
|
||||
for (i = 0; i < platform_id_count; i++) {
|
||||
temp_buff[0] = '\0';
|
||||
clGetPlatformInfo(platform_ids[i], CL_PLATFORM_NAME, sizeof(temp_buff), temp_buff, NULL);
|
||||
printf("Platform ID %d: %s\n", i, temp_buff);
|
||||
}
|
||||
|
||||
clGetDeviceIDs(platform_ids[0], CL_DEVICE_TYPE_ALL, 0, NULL,
|
||||
&device_id_count);
|
||||
printf("Device in Platform 0 count: %u\n",
|
||||
(unsigned int)device_id_count);
|
||||
|
||||
if (device_id_count == 0)
|
||||
return -1;
|
||||
|
||||
device_ids = (cl_device_id *) malloc(sizeof(cl_device_id)
|
||||
*device_id_count);
|
||||
|
||||
clGetDeviceIDs(platform_ids[0], CL_DEVICE_TYPE_ALL, device_id_count,
|
||||
device_ids, NULL);
|
||||
|
||||
for (i = 0; i < device_id_count; i++) {
|
||||
temp_buff[0] = '\0';
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_NAME, sizeof(temp_buff), temp_buff, NULL);
|
||||
printf("Device ID %d: %s\n", i, temp_buff);
|
||||
}
|
||||
|
||||
|
||||
context = clCreateContext(NULL, 1, &device_ids[0], NULL, NULL, &error);
|
||||
check_error(error);
|
||||
|
||||
/* Drawing code end */
|
||||
cairo_restore(cr);
|
||||
queue = clCreateCommandQueue(context, device_ids[0], 0, &error);
|
||||
|
||||
dat_buff = clCreateBuffer(context, CL_MEM_WRITE_ONLY |
|
||||
CL_MEM_COPY_HOST_PTR,
|
||||
3*data_size, buff->mandelbrot_buffer, &error);
|
||||
check_error(error);
|
||||
|
||||
load_kernel_from_file("cl_kernels/mandelbrot.cl", &source_code);
|
||||
program = create_program(source_code, context);
|
||||
|
||||
/* Compile the source code */
|
||||
check_error(clBuildProgram(program, device_id_count,
|
||||
device_ids, NULL, NULL, NULL));
|
||||
kernel = clCreateKernel(program, "mandelbrot", &error);
|
||||
|
||||
|
||||
/* Setting the arguments */
|
||||
clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&dat_buff);
|
||||
clSetKernelArg(kernel, 1, sizeof(unsigned int), (void *)&buff->iterations);
|
||||
clSetKernelArg(kernel, 2, sizeof(double), (void *)&buff->center_x);
|
||||
clSetKernelArg(kernel, 3, sizeof(double), (void *)&buff->center_y);
|
||||
clSetKernelArg(kernel, 4, sizeof(double), (void *)&buff->x_span);
|
||||
clSetKernelArg(kernel, 5, sizeof(double), (void *)&buff->y_span);
|
||||
clSetKernelArg(kernel, 6, sizeof(unsigned int), (void *)&buff->width);
|
||||
clSetKernelArg(kernel, 7, sizeof(unsigned int), (void *)&buff->height);
|
||||
|
||||
ret = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &data_size, &work_size, 0, NULL, NULL);
|
||||
check_error(ret);
|
||||
|
||||
clEnqueueReadBuffer(queue, dat_buff, CL_TRUE, 0, data_size*3, buff->mandelbrot_buffer, 0, NULL, NULL);
|
||||
|
||||
ret = clFlush(queue);
|
||||
ret = clFinish(queue);
|
||||
ret = clReleaseKernel(kernel);
|
||||
ret = clReleaseProgram(program);
|
||||
ret = clReleaseMemObject(dat_buff);
|
||||
ret = clReleaseCommandQueue(queue);
|
||||
ret = clReleaseContext(context);
|
||||
free(platform_ids);
|
||||
free(device_ids);
|
||||
|
||||
return 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void calculate_mandelbrot(struct canvas_buffer *buff)
|
||||
float vertices[] = {
|
||||
// Vertex Texture
|
||||
-0.95f, -0.95f, 0.0f, 0.0f, 0.0f, // bottom left
|
||||
-0.95f, 0.95f, 0.0f, 0.0f, 1.0f, // top left
|
||||
0.95f, -0.95f, 0.0f, 1.0f, 0.0f, // bottom right
|
||||
0.95f, 0.95f, 0.0f, 1.0f, 1.0f, // top right
|
||||
};
|
||||
|
||||
unsigned int indices[] = {
|
||||
0, 1, 2,
|
||||
2, 1, 3
|
||||
};
|
||||
|
||||
static unsigned int vertex_buffer_object;
|
||||
static unsigned int element_buffer_object;
|
||||
static unsigned int vertex_array_object;
|
||||
static unsigned int shader_program_id;
|
||||
static unsigned int texture_id;
|
||||
|
||||
gboolean render(GtkGLArea *gl_area, GdkGLContext *context, gpointer user_data)
|
||||
{
|
||||
double val_per_x_pixel;
|
||||
double val_per_y_pixel;
|
||||
unsigned int i;
|
||||
unsigned int pixel_x;
|
||||
unsigned int pixel_y;
|
||||
double point_real, point_imag;
|
||||
double z_real, z_imag;
|
||||
double z2_real, z2_imag;
|
||||
int zoom_loc;
|
||||
static float zoom = 1.0f;
|
||||
|
||||
gtk_gl_area_make_current(gl_area);
|
||||
|
||||
if (!buff)
|
||||
return;
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
/* Setup the calculation data */
|
||||
val_per_x_pixel = (buff->x_span) / (buff->width - 1);
|
||||
val_per_y_pixel = (buff->y_span) / (buff->height - 1);
|
||||
glUseProgram(shader_program_id);
|
||||
zoom_loc = glGetUniformLocation(shader_program_id, "zoom");
|
||||
glUniform1f(zoom_loc, zoom);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
glBindVertexArray(vertex_array_object);
|
||||
//glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
|
||||
for (pixel_y = 0; pixel_y < buff->height; pixel_y++) {
|
||||
for (pixel_x = 0; pixel_x < buff->width; pixel_x++) {
|
||||
point_real = (((double)pixel_x - (double)(buff->width - 1) / 2)) * val_per_x_pixel + buff->center_x;
|
||||
point_imag = (((double)pixel_y - (double)(buff->height - 1) / 2)) * val_per_y_pixel + buff->center_y;
|
||||
glFlush();
|
||||
|
||||
z_real = 0.0;
|
||||
z_imag = 0.0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check for convergence */
|
||||
for (i = 0; i < buff->iterations; i++) {
|
||||
void realize(GtkGLArea *gl_area, gpointer user_data)
|
||||
{
|
||||
|
||||
z2_real = z_real * z_real - z_imag * z_imag;
|
||||
z2_imag = 2.0 * z_real * z_imag;
|
||||
unsigned int vertex_shader_id;
|
||||
unsigned int fragment_shader_id;
|
||||
struct canvas_buffer *mandelbrot_buff = (struct canvas_buffer *)user_data;
|
||||
|
||||
z_real = z2_real + point_real;
|
||||
z_imag = z2_imag + point_imag;
|
||||
int success;
|
||||
char info_log[512];
|
||||
|
||||
if ((z_real * z_real + z_imag * z_imag) >= 4.0)
|
||||
break;
|
||||
}
|
||||
gtk_gl_area_make_current(gl_area);
|
||||
glClearColor(0.2, 0.2, 0.2, 1);
|
||||
|
||||
buff->mandelbrot_buffer[pixel_y * buff->width + pixel_x] = i;
|
||||
}
|
||||
glGenVertexArrays(1, &vertex_array_object);
|
||||
glBindVertexArray(vertex_array_object);
|
||||
|
||||
glGenBuffers(1, &vertex_buffer_object);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &element_buffer_object);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_object);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader_id, 1, &vertex_shader, NULL);
|
||||
glCompileShader(vertex_shader_id);
|
||||
glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &success);
|
||||
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(vertex_shader_id, 512, NULL, info_log);
|
||||
printf("%s\n", info_log);
|
||||
} else {
|
||||
printf("Vertex shader compilation successful\n");
|
||||
}
|
||||
|
||||
fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader_id, 1, &orange_framgment_shader, NULL);
|
||||
glCompileShader(fragment_shader_id);
|
||||
glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &success);
|
||||
|
||||
}
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(fragment_shader_id, 512, NULL, info_log);
|
||||
printf("%s\n", info_log);
|
||||
} else {
|
||||
printf("Fragment shader compilation successful\n");
|
||||
}
|
||||
|
||||
shader_program_id = glCreateProgram();
|
||||
glAttachShader(shader_program_id, vertex_shader_id);
|
||||
glAttachShader(shader_program_id, fragment_shader_id);
|
||||
glLinkProgram(shader_program_id);
|
||||
|
||||
glGetShaderiv(shader_program_id, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(shader_program_id, 512, NULL, info_log);
|
||||
printf("%s\n", info_log);
|
||||
} else {
|
||||
printf("Shader Core linked successfully\n");
|
||||
}
|
||||
|
||||
glUseProgram(shader_program_id);
|
||||
glDeleteShader(vertex_shader_id);
|
||||
glDeleteShader(fragment_shader_id);
|
||||
|
||||
|
||||
int f(void * a)
|
||||
{
|
||||
return 1;
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mandelbrot_buff->width, mandelbrot_buff->height,
|
||||
0, GL_RGB, GL_UNSIGNED_BYTE, mandelbrot_buff->mandelbrot_buffer);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GtkDrawingArea *drawing_area;
|
||||
GtkGLArea *gl_area;
|
||||
GtkWindow *window;
|
||||
GtkBuilder *builder;
|
||||
static struct canvas_buffer mandelbrot_buff;
|
||||
clock_t start, end;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
builder = gtk_builder_new_from_resource("/main.glade");
|
||||
|
||||
drawing_area = GTK_DRAWING_AREA(gtk_builder_get_object(builder, "drawing-area"));
|
||||
window = GTK_WINDOW(gtk_builder_get_object(builder, "main-window"));
|
||||
|
||||
g_signal_connect(window, "delete-event", G_CALLBACK(on_main_window_close), NULL);
|
||||
g_signal_connect(G_OBJECT(drawing_area),
|
||||
"draw", G_CALLBACK(drawing_callback), (gpointer)&mandelbrot_buff);
|
||||
|
||||
|
||||
mandelbrot_buff.x_span = 0.1;//2.8;
|
||||
mandelbrot_buff.y_span = 0.1;//2.25;
|
||||
mandelbrot_buff.center_x = -0.6;
|
||||
mandelbrot_buff.center_y = 0.44;
|
||||
mandelbrot_buff.width = 4000;
|
||||
mandelbrot_buff.height = 4000;
|
||||
mandelbrot_buff.iterations = 1000;
|
||||
mandelbrot_buff.mandelbrot_buffer = NULL;
|
||||
|
||||
printf("Compile and run Mandelbrot on OpenCL HW\n");
|
||||
start = clock();
|
||||
calculate_mandelbrot(&mandelbrot_buff);
|
||||
end = clock();
|
||||
printf("Calculation finished. Time needed: %lf ms\n", ((double)(end - start)) / CLOCKS_PER_SEC * 1000.0);
|
||||
|
||||
|
||||
gl_area = GTK_GL_AREA(gtk_gl_area_new());
|
||||
gtk_gl_area_set_auto_render(gl_area, TRUE);
|
||||
gtk_widget_set_vexpand(GTK_WIDGET(gl_area), TRUE);
|
||||
gtk_widget_set_hexpand(GTK_WIDGET(gl_area), TRUE);
|
||||
g_signal_connect(gl_area, "realize", G_CALLBACK(realize), &mandelbrot_buff);
|
||||
g_signal_connect(gl_area, "render", G_CALLBACK(render), NULL);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(gl_area));
|
||||
gtk_widget_show(GTK_WIDGET(gl_area));
|
||||
|
||||
g_object_unref(builder);
|
||||
|
||||
thrd_t t;
|
||||
thrd_create(&t, f, NULL);
|
||||
|
||||
|
||||
mandelbrot_buff.x_span = 2.8;
|
||||
mandelbrot_buff.y_span = 2.25;
|
||||
mandelbrot_buff.center_x = -0.5;
|
||||
mandelbrot_buff.center_y = 0.0;
|
||||
mandelbrot_buff.width = 1900;
|
||||
mandelbrot_buff.height = 1000;
|
||||
mandelbrot_buff.iterations = 300;
|
||||
mandelbrot_buff.mandelbrot_buffer = (unsigned int *)malloc(sizeof(unsigned int) * mandelbrot_buff.height * mandelbrot_buff.width);
|
||||
calculate_mandelbrot(&mandelbrot_buff);
|
||||
|
||||
gtk_gl_area_make_current(gl_area);
|
||||
|
||||
printf("Gui will be displayed\n");
|
||||
gtk_main();
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user