Compare commits
2 Commits
main
...
double-pre
Author | SHA1 | Date | |
---|---|---|---|
a8acdc4b01 | |||
03364ad387 |
7
README
7
README
@ -10,10 +10,3 @@ double precision shaders.
|
|||||||
To build and run:
|
To build and run:
|
||||||
|
|
||||||
./build.sh && ./gpu-frac
|
./build.sh && ./gpu-frac
|
||||||
|
|
||||||
Since both GLSL and C use CPP directives, I parameterised the program
|
|
||||||
a bunch and stuck a load of cool presets in config.h, which can be
|
|
||||||
simply be uncommented and commented as is required. All the #ifdefs
|
|
||||||
make the code a bit harder to read but it's nice being able to twiddle
|
|
||||||
numbers and change the visualisation without messing around editing
|
|
||||||
and commenting out code.
|
|
||||||
|
2
build.sh
2
build.sh
@ -2,4 +2,4 @@
|
|||||||
set -e
|
set -e
|
||||||
glslc -fshader-stage=vert vert_shader.glsl -o vert_shader.spv
|
glslc -fshader-stage=vert vert_shader.glsl -o vert_shader.spv
|
||||||
glslc -fshader-stage=frag frag_shader.glsl -o frag_shader.spv
|
glslc -fshader-stage=frag frag_shader.glsl -o frag_shader.spv
|
||||||
clang -std=c11 -pedantic -Wall -Wextra -lglfw -lm -lvulkan main.c -o gpu-fractal
|
clang -std=c11 -pedantic -Wall -Wextra -lglfw -lvulkan main.c -o gpu-fractal
|
||||||
|
77
config.h
77
config.h
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Camden Dixie O'Brien
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAXITER 1000
|
|
||||||
|
|
||||||
// Pretty Julia set zoom
|
|
||||||
//#define SS 9
|
|
||||||
//#define JULIA
|
|
||||||
//#define JULIA_C_RE 0.285
|
|
||||||
//#define JULIA_C_IM 0.010
|
|
||||||
//#define CENTRE_RE -0.47353731
|
|
||||||
//#define CENTRE_IM -0.18894516
|
|
||||||
//#define ZOOMRATE 0.01
|
|
||||||
|
|
||||||
// Cool zoomy swirly animated Julia set
|
|
||||||
//#define SS 9
|
|
||||||
//#define JULIA
|
|
||||||
//#define JULIA_C_RE 0.300
|
|
||||||
//#define JULIA_DTHETA 0.00001
|
|
||||||
//#define ZOOMRATE 0.0004
|
|
||||||
|
|
||||||
// Nice Mandelbrot zoom
|
|
||||||
//#define SS 9
|
|
||||||
//#define CENTRE_RE -0.743643887
|
|
||||||
//#define CENTRE_IM 0.131825904
|
|
||||||
//#define ZOOMRATE 0.004
|
|
||||||
|
|
||||||
// Cool warping Mandelbrot zoom
|
|
||||||
//#define SS 4
|
|
||||||
//#define CENTRE_RE -0.900000000
|
|
||||||
//#define POWRATE 0.0001
|
|
||||||
//#define ZOOMRATE 0.001
|
|
||||||
|
|
||||||
// Funky swirly, warping Julia zoom
|
|
||||||
//#define SS 9
|
|
||||||
//#define JULIA
|
|
||||||
//#define JULIA_C_RE 0.5
|
|
||||||
//#define JULIA_C_IM 0.5
|
|
||||||
//#define CENTRE_RE 0.5
|
|
||||||
//#define CENTRE_IM -0.5
|
|
||||||
//#define JULIA_DTHETA -0.00002
|
|
||||||
//#define POWRATE 0.0001
|
|
||||||
//#define ZOOMRATE 0.0003
|
|
||||||
|
|
||||||
// Cool tendril stuff (complex power)
|
|
||||||
//#define SS 4
|
|
||||||
//#define CPOW_DTHETA 0.000
|
|
||||||
//#define MAXMAG 100.0
|
|
||||||
//#define CENTRE_RE -0.84880415
|
|
||||||
//#define CENTRE_IM 0.03921157
|
|
||||||
//#define CPOW_START_RE 1.96550429
|
|
||||||
//#define CPOW_START_IM 0.36985874
|
|
||||||
//#define ZOOMRATE 0.01
|
|
||||||
|
|
||||||
// ??
|
|
||||||
//#define SS 4
|
|
||||||
//#define THING
|
|
||||||
//#define JULIA_C_RE -0.9999999506519784
|
|
||||||
//#define JULIA_C_IM 3.141592601914583e-4
|
|
||||||
//#define JULIA_DTHETA 0.00001
|
|
||||||
//#define MAXMAG 100.0
|
|
||||||
//#define STARTSCALE 4
|
|
||||||
//#define ZOOMRATE 0.01
|
|
||||||
|
|
||||||
// Funky complex power julia set
|
|
||||||
#define SS 4
|
|
||||||
#define JULIA
|
|
||||||
#define JULIA_C_RE -0.010
|
|
||||||
#define JULIA_C_IM 0.285
|
|
||||||
#define JULIA_DTHETA 0.0001
|
|
||||||
#define CPOW_START_RE 0.0
|
|
||||||
#define CPOW_START_IM 2.0
|
|
||||||
#define CPOW_DTHETA 0.0001
|
|
||||||
#define MAXMAG 100.0
|
|
||||||
#define STARTSCALE 1
|
|
132
frag_shader.glsl
132
frag_shader.glsl
@ -4,142 +4,54 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#version 450
|
#version 450
|
||||||
|
#extension GL_ARB_gpu_shader_fp64 : enable
|
||||||
|
|
||||||
#include "config.h"
|
#define MAXITER 1000
|
||||||
|
|
||||||
#define NCOLS 8
|
|
||||||
|
|
||||||
#if !defined(CPOW_DTHETA) && !defined(THING)
|
|
||||||
#define MAXMAG 2.0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 out_colour;
|
layout(location = 0) out vec4 out_colour;
|
||||||
|
|
||||||
layout(push_constant) uniform Constants {
|
layout(push_constant) uniform Constants {
|
||||||
vec2 img_size;
|
dvec2 img_size;
|
||||||
#if defined(JULIA) || defined(THING)
|
dvec2 shift;
|
||||||
vec2 julia;
|
double zoom;
|
||||||
#endif
|
|
||||||
vec2 centre;
|
|
||||||
#ifdef CPOW_DTHETA
|
|
||||||
vec2 cpow;
|
|
||||||
#endif
|
|
||||||
#ifdef POWRATE
|
|
||||||
float zpow;
|
|
||||||
#endif
|
|
||||||
float scale;
|
|
||||||
} params;
|
} params;
|
||||||
|
|
||||||
vec3 incol = vec3(0.000000, 0.014444, 0.027321);
|
vec2 ss_offsets[4] = vec2[](
|
||||||
|
|
||||||
vec3 palette[NCOLS] = vec3[](
|
|
||||||
vec3(0.000000, 0.049707, 0.107023),
|
|
||||||
vec3(0.025187, 0.064803, 0.177888),
|
|
||||||
vec3(0.254152, 0.080220, 0.274677),
|
|
||||||
vec3(0.502886, 0.080220, 0.278894),
|
|
||||||
vec3(1.000000, 0.124772, 0.119538),
|
|
||||||
vec3(1.000000, 0.234551, 0.030713),
|
|
||||||
vec3(1.000000, 0.381326, 0.000000),
|
|
||||||
vec3(1.000000, 0.651406, 0.215861)
|
|
||||||
);
|
|
||||||
|
|
||||||
#if SS == 4
|
|
||||||
vec2 ss_offsets[SS] = vec2[](
|
|
||||||
vec2(-0.25, -0.25),
|
vec2(-0.25, -0.25),
|
||||||
vec2( 0.25, -0.25),
|
vec2( 0.25, -0.25),
|
||||||
vec2(-0.25, 0.25),
|
vec2(-0.25, 0.25),
|
||||||
vec2( 0.25, 0.25)
|
vec2( 0.25, 0.25)
|
||||||
);
|
);
|
||||||
#elif SS == 9
|
|
||||||
vec2 ss_offsets[SS] = vec2[](
|
|
||||||
vec2(-0.33, -0.33), vec2(0.0, -0.33), vec2(0.33, -0.33),
|
|
||||||
vec2(-0.33, 0.0), vec2(0.0, 0.0), vec2(0.33, 0.0),
|
|
||||||
vec2(-0.33, 0.33), vec2(0.0, 0.33), vec2(0.33, 0.33)
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
#error "Unsupported supersampling count"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec2 maptoz(vec2 xy)
|
dvec2 maptoz(vec2 xy)
|
||||||
{
|
{
|
||||||
float aspect = params.img_size.x / params.img_size.y;
|
dvec2 dxy = dvec2(xy);
|
||||||
vec2 z = 4.0 * (xy / params.img_size.xy - 0.5);
|
dvec2 uv = ((dxy / params.img_size.xy) * 4.0LF - 2.0LF);
|
||||||
z.x *= aspect;
|
return params.zoom * uv + params.shift;
|
||||||
return params.scale * z + params.centre;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 cmul(vec2 a, vec2 b)
|
double mandelbrot(dvec2 c) {
|
||||||
{
|
dvec2 z = dvec2(0.0LF, 0.0LF);
|
||||||
return vec2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 cexp(vec2 z)
|
|
||||||
{
|
|
||||||
return exp(z.x) * vec2(cos(z.y), sin(z.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 cln(vec2 z)
|
|
||||||
{
|
|
||||||
return vec2(log(length(z)), atan(z.y, z.x));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 cpow(vec2 z, vec2 p)
|
|
||||||
{
|
|
||||||
if (z.x == 0.0 && z.y == 0.0) return vec2(0.0, 0.0);
|
|
||||||
return cexp(cmul(p, cln(z)));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 zpow(vec2 z, float p)
|
|
||||||
{
|
|
||||||
float mag = pow(length(z), p);
|
|
||||||
float arg = p * atan(z.y, z.x);
|
|
||||||
return mag * vec2(cos(arg), sin(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
int fractal(vec2 c) {
|
|
||||||
#ifdef JULIA
|
|
||||||
vec2 z = c;
|
|
||||||
c = params.julia;
|
|
||||||
#else
|
|
||||||
vec2 z = vec2(0.0, 0.0);
|
|
||||||
#endif
|
|
||||||
for (int i = 0; i < MAXITER; ++i) {
|
for (int i = 0; i < MAXITER; ++i) {
|
||||||
#ifdef CPOW_DTHETA
|
z = dvec2(z.x * z.x - z.y * z.y, 2.0LF * z.x * z.y) + c;
|
||||||
z = cpow(z, params.cpow) + c;
|
if (length(z) > 2.0LF)
|
||||||
#elif defined(POWRATE)
|
return double(i) / double(MAXITER);
|
||||||
z = zpow(z, params.zpow) + c;
|
|
||||||
#elif defined(THING)
|
|
||||||
z = cpow(z, c) + params.julia;
|
|
||||||
#else
|
|
||||||
z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + c;
|
|
||||||
#endif
|
|
||||||
if (length(z) > MAXMAG)
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
return -1;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 colour(int i) {
|
vec3 colour(double i) {
|
||||||
if (i == -1) {
|
float fi = float(i);
|
||||||
return incol;
|
return vec3(fi, fi * fi, fi * fi * fi);
|
||||||
} else {
|
|
||||||
float c = float(NCOLS) * sqrt(float(i) / float(MAXITER));
|
|
||||||
int fc = int(floor(c));
|
|
||||||
int cc = int(ceil(c));
|
|
||||||
float p = c - float(fc);
|
|
||||||
p = smoothstep(0.0, 1.0, p);
|
|
||||||
return mix(palette[fc], palette[cc], p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 c;
|
dvec2 c;
|
||||||
vec3 col = vec3(0.0, 0.0, 0.0);
|
vec3 col = vec3(0.0, 0.0, 0.0);
|
||||||
for (int i = 0; i < SS; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
c = maptoz(gl_FragCoord.xy + ss_offsets[i]);
|
c = maptoz(gl_FragCoord.xy + ss_offsets[i]);
|
||||||
col += colour(fractal(c));
|
col += colour(mandelbrot(c));
|
||||||
}
|
}
|
||||||
col /= SS;
|
|
||||||
out_colour = vec4(col, 1.0);
|
out_colour = vec4(col, 1.0);
|
||||||
}
|
}
|
||||||
|
247
main.c
247
main.c
@ -5,12 +5,8 @@
|
|||||||
|
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <complex.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -19,130 +15,25 @@
|
|||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define CLAMP(x, min, max) MAX((min), MIN(x, (max)))
|
#define CLAMP(x, min, max) MAX((min), MIN(x, (max)))
|
||||||
|
|
||||||
|
#define PHYSICAL_DEV_BUFFER_SIZE 8
|
||||||
#define QUEUE_FAMILY_PROP_BUFFER_SIZE 16
|
#define QUEUE_FAMILY_PROP_BUFFER_SIZE 16
|
||||||
#define EXT_PROP_BUFFER_SIZE 256
|
#define EXT_PROP_BUFFER_SIZE 256
|
||||||
#define SURFACE_FMT_BUFFER_SIZE 64
|
#define SURFACE_FMT_BUFFER_SIZE 64
|
||||||
#define PRESENT_MODE_BUFFER_SIZE 8
|
#define PRESENT_MODE_BUFFER_SIZE 8
|
||||||
#define SWAPCHAIN_IMG_BUFFER_SIZE 4
|
#define SWAPCHAIN_IMG_BUFFER_SIZE 4
|
||||||
|
|
||||||
#define MAX_SHADER_SIZE (8 * 1024)
|
#define MAX_SHADER_SIZE (4 * 1024)
|
||||||
|
|
||||||
#define FASTFORWARD_RATE 100
|
|
||||||
|
|
||||||
#if defined(CPOW_DTHETA) && defined(POWRATE)
|
|
||||||
#error "Cannot define CPOW_DTHETA and POWRATE simulataneously"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef STARTSCALE
|
|
||||||
#define STARTSCALE 1.0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float width, height;
|
double width, height;
|
||||||
#if defined(JULIA) || defined(THING)
|
|
||||||
struct {
|
struct {
|
||||||
float re, im;
|
double x, y;
|
||||||
} julia;
|
} shift;
|
||||||
#endif
|
double zoom;
|
||||||
struct {
|
|
||||||
float re, im;
|
|
||||||
} centre;
|
|
||||||
#ifdef CPOW_DTHETA
|
|
||||||
struct {
|
|
||||||
float re, im;
|
|
||||||
} cpow;
|
|
||||||
#endif
|
|
||||||
#ifdef POWRATE
|
|
||||||
float zpow;
|
|
||||||
#endif
|
|
||||||
float scale;
|
|
||||||
} params_t;
|
} params_t;
|
||||||
|
|
||||||
static const char *layers[] = { "VK_LAYER_KHRONOS_validation" };
|
static const char *layers[] = { "VK_LAYER_KHRONOS_validation" };
|
||||||
static const char *extensions[] = {
|
static const char *swapchain_ext_name = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NEXTENSIONS (sizeof(extensions) / sizeof(extensions[0]))
|
|
||||||
|
|
||||||
// Initial parameters
|
|
||||||
static params_t params = {
|
|
||||||
#if defined(JULIA) || defined(THING)
|
|
||||||
.julia = {
|
|
||||||
#ifdef JULIA_C_RE
|
|
||||||
.re = JULIA_C_RE,
|
|
||||||
#endif
|
|
||||||
#ifdef JULIA_C_IM
|
|
||||||
.im = JULIA_C_IM,
|
|
||||||
#endif
|
|
||||||
},
|
|
||||||
#endif
|
|
||||||
#if defined(CENTRE_RE) || defined(CENTRE_IM)
|
|
||||||
.centre = {
|
|
||||||
#ifdef CENTRE_RE
|
|
||||||
.re = CENTRE_RE,
|
|
||||||
#endif
|
|
||||||
#ifdef CENTRE_IM
|
|
||||||
.im = CENTRE_IM,
|
|
||||||
#endif
|
|
||||||
},
|
|
||||||
#endif
|
|
||||||
#ifdef CPOW_DTHETA
|
|
||||||
.cpow = { .re = CPOW_START_RE, .im = CPOW_START_IM },
|
|
||||||
#endif
|
|
||||||
#ifdef POWRATE
|
|
||||||
.zpow = 2.0,
|
|
||||||
#endif
|
|
||||||
.scale = STARTSCALE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool paused = false, fastforward = false;
|
|
||||||
|
|
||||||
static void
|
|
||||||
mouse_button_callback(GLFWwindow *window, int button, int action, int mods)
|
|
||||||
{
|
|
||||||
(void)window;
|
|
||||||
(void)button;
|
|
||||||
(void)mods;
|
|
||||||
|
|
||||||
if (action == GLFW_RELEASE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
double x, y;
|
|
||||||
glfwGetCursorPos(window, &x, &y);
|
|
||||||
|
|
||||||
double zx = 4.0 * (x / params.width - 0.5);
|
|
||||||
double zy = 4.0 * (y / params.height - 0.5);
|
|
||||||
zx *= params.width / params.height;
|
|
||||||
|
|
||||||
zx = params.scale * zx + params.centre.re;
|
|
||||||
zy = params.scale * zy + params.centre.im;
|
|
||||||
|
|
||||||
printf("CLICKED: %.8f + %.8fi\n", zx, zy);
|
|
||||||
params.centre.re = zx;
|
|
||||||
params.centre.im = zy;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
|
||||||
{
|
|
||||||
(void)window;
|
|
||||||
(void)scancode;
|
|
||||||
(void)mods;
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case GLFW_KEY_SPACE:
|
|
||||||
if (action == GLFW_PRESS)
|
|
||||||
paused = !paused;
|
|
||||||
break;
|
|
||||||
case GLFW_KEY_F:
|
|
||||||
if (action == GLFW_PRESS)
|
|
||||||
fastforward = true;
|
|
||||||
else if (action == GLFW_RELEASE)
|
|
||||||
fastforward = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static VkShaderModule load_shader_module(VkDevice dev, const char *path)
|
static VkShaderModule load_shader_module(VkDevice dev, const char *path)
|
||||||
{
|
{
|
||||||
@ -168,24 +59,18 @@ static VkShaderModule load_shader_module(VkDevice dev, const char *path)
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// Set up window
|
// Set up window and surface
|
||||||
glfwInit();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
GLFWwindow *window
|
||||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
= glfwCreateWindow(900, 900, "GPU Fractal", NULL, NULL);
|
||||||
GLFWwindow *window = glfwCreateWindow(
|
|
||||||
mode->width, mode->height, "GPU Fractal", monitor, NULL);
|
|
||||||
assert(window);
|
assert(window);
|
||||||
|
|
||||||
// Register input callbacks
|
|
||||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
|
||||||
glfwSetKeyCallback(window, key_callback);
|
|
||||||
|
|
||||||
// Initialise Vulkan instance.
|
// Initialise Vulkan instance.
|
||||||
const VkApplicationInfo app_info = {
|
const VkApplicationInfo app_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
.pApplicationName = "GPU Fractal",
|
.pApplicationName = "Vulkan Test",
|
||||||
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
.pEngineName = "No Engine",
|
.pEngineName = "No Engine",
|
||||||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
@ -212,10 +97,22 @@ int main(void)
|
|||||||
assert(result == VK_SUCCESS);
|
assert(result == VK_SUCCESS);
|
||||||
|
|
||||||
// Select a physical device
|
// Select a physical device
|
||||||
|
VkPhysicalDevice physical_devs[PHYSICAL_DEV_BUFFER_SIZE];
|
||||||
|
uint32_t dev_count = PHYSICAL_DEV_BUFFER_SIZE;
|
||||||
|
result = vkEnumeratePhysicalDevices(inst, &dev_count, physical_devs);
|
||||||
|
assert(result == VK_SUCCESS);
|
||||||
|
bool found_physical_dev = false;
|
||||||
VkPhysicalDevice physical_dev;
|
VkPhysicalDevice physical_dev;
|
||||||
uint32_t dev_count = 1;
|
for (unsigned i = 0; i < dev_count; ++i) {
|
||||||
result = vkEnumeratePhysicalDevices(inst, &dev_count, &physical_dev);
|
// Check that the device supports double precision
|
||||||
assert(result == VK_SUCCESS || result == VK_INCOMPLETE);
|
VkPhysicalDeviceFeatures features;
|
||||||
|
vkGetPhysicalDeviceFeatures(physical_devs[i], &features);
|
||||||
|
if (features.shaderFloat64) {
|
||||||
|
physical_dev = physical_devs[i];
|
||||||
|
found_physical_dev = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(found_physical_dev);
|
||||||
|
|
||||||
// Select queue family
|
// Select queue family
|
||||||
uint32_t queue_family_count = QUEUE_FAMILY_PROP_BUFFER_SIZE;
|
uint32_t queue_family_count = QUEUE_FAMILY_PROP_BUFFER_SIZE;
|
||||||
@ -239,28 +136,6 @@ int main(void)
|
|||||||
}
|
}
|
||||||
assert(found_queue_family);
|
assert(found_queue_family);
|
||||||
|
|
||||||
// Check that the physical device supports all extensions
|
|
||||||
uint32_t ext_count = EXT_PROP_BUFFER_SIZE;
|
|
||||||
VkExtensionProperties ext_props[EXT_PROP_BUFFER_SIZE];
|
|
||||||
result = vkEnumerateDeviceExtensionProperties(
|
|
||||||
physical_dev, NULL, &ext_count, ext_props);
|
|
||||||
assert(result == VK_SUCCESS);
|
|
||||||
bool supported[NEXTENSIONS] = { 0 };
|
|
||||||
for (unsigned i = 0; i < ext_count; ++i) {
|
|
||||||
for (unsigned j = 0; j < NEXTENSIONS; ++j) {
|
|
||||||
if (strcmp(extensions[j], ext_props[i].extensionName) == 0) {
|
|
||||||
supported[j] = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (unsigned j = 0; j < NEXTENSIONS; ++j) {
|
|
||||||
if (!supported[j]) {
|
|
||||||
fprintf(stderr, "Unsupported: %s\n", extensions[j]);
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the logical device and get the queue handle.
|
// Create the logical device and get the queue handle.
|
||||||
float queue_priority = 1.0;
|
float queue_priority = 1.0;
|
||||||
const VkDeviceQueueCreateInfo queue_create_info = {
|
const VkDeviceQueueCreateInfo queue_create_info = {
|
||||||
@ -269,12 +144,16 @@ int main(void)
|
|||||||
.queueCount = 1,
|
.queueCount = 1,
|
||||||
.pQueuePriorities = &queue_priority,
|
.pQueuePriorities = &queue_priority,
|
||||||
};
|
};
|
||||||
|
const VkPhysicalDeviceFeatures enabled_features = {
|
||||||
|
.shaderFloat64 = VK_TRUE,
|
||||||
|
};
|
||||||
const VkDeviceCreateInfo dev_create_info = {
|
const VkDeviceCreateInfo dev_create_info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
.pQueueCreateInfos = &queue_create_info,
|
.pQueueCreateInfos = &queue_create_info,
|
||||||
.queueCreateInfoCount = 1,
|
.queueCreateInfoCount = 1,
|
||||||
.enabledExtensionCount = NEXTENSIONS,
|
.enabledExtensionCount = 1,
|
||||||
.ppEnabledExtensionNames = extensions,
|
.ppEnabledExtensionNames = &swapchain_ext_name,
|
||||||
|
.pEnabledFeatures = &enabled_features,
|
||||||
};
|
};
|
||||||
VkDevice dev;
|
VkDevice dev;
|
||||||
result = vkCreateDevice(physical_dev, &dev_create_info, NULL, &dev);
|
result = vkCreateDevice(physical_dev, &dev_create_info, NULL, &dev);
|
||||||
@ -282,6 +161,21 @@ int main(void)
|
|||||||
VkQueue queue;
|
VkQueue queue;
|
||||||
vkGetDeviceQueue(dev, queue_family, 0, &queue);
|
vkGetDeviceQueue(dev, queue_family, 0, &queue);
|
||||||
|
|
||||||
|
// Check that the physical device has swap chain support
|
||||||
|
uint32_t ext_count = EXT_PROP_BUFFER_SIZE;
|
||||||
|
VkExtensionProperties ext_props[EXT_PROP_BUFFER_SIZE];
|
||||||
|
result = vkEnumerateDeviceExtensionProperties(
|
||||||
|
physical_dev, NULL, &ext_count, ext_props);
|
||||||
|
assert(result == VK_SUCCESS);
|
||||||
|
bool swapchain_support = false;
|
||||||
|
for (unsigned i = 0; i < ext_count; ++i) {
|
||||||
|
if (strcmp(swapchain_ext_name, ext_props[i].extensionName) == 0) {
|
||||||
|
swapchain_support = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(swapchain_support);
|
||||||
|
|
||||||
// Select a surface format, preferring R8G8B8A8_SRGB with
|
// Select a surface format, preferring R8G8B8A8_SRGB with
|
||||||
// SRGB_NONLINEAR colour space.
|
// SRGB_NONLINEAR colour space.
|
||||||
uint32_t surface_fmt_count = SURFACE_FMT_BUFFER_SIZE;
|
uint32_t surface_fmt_count = SURFACE_FMT_BUFFER_SIZE;
|
||||||
@ -584,15 +478,15 @@ int main(void)
|
|||||||
result = vkCreateFence(dev, &fence_config, NULL, &in_flight);
|
result = vkCreateFence(dev, &fence_config, NULL, &in_flight);
|
||||||
assert(result == VK_SUCCESS);
|
assert(result == VK_SUCCESS);
|
||||||
|
|
||||||
// Initialise shader parameters
|
params_t params = {
|
||||||
params.width = (float)swapchain_extent.width;
|
.width = (double)swapchain_extent.width,
|
||||||
params.height = (float)swapchain_extent.height;
|
.height = (double)swapchain_extent.height,
|
||||||
#ifdef JULIA_DTHETA
|
.shift = {
|
||||||
const double complex julia_rotz = cexp(I * JULIA_DTHETA);
|
.x = -0.743643887037158704752191506114774,
|
||||||
#endif
|
.y = 0.131825904205311970493132056385139,
|
||||||
#ifdef CPOW_DTHETA
|
},
|
||||||
const double complex cpow_rotz = cexp(I * CPOW_DTHETA);
|
.zoom = 1.0,
|
||||||
#endif
|
};
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
@ -629,7 +523,6 @@ int main(void)
|
|||||||
vkCmdBeginRenderPass(
|
vkCmdBeginRenderPass(
|
||||||
cmd_buf, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
|
cmd_buf, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
// Send parameters
|
|
||||||
vkCmdPushConstants(
|
vkCmdPushConstants(
|
||||||
cmd_buf, pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
|
cmd_buf, pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
|
||||||
sizeof(params), ¶ms);
|
sizeof(params), ¶ms);
|
||||||
@ -672,32 +565,8 @@ int main(void)
|
|||||||
result = vkQueuePresentKHR(queue, &present_info);
|
result = vkQueuePresentKHR(queue, &present_info);
|
||||||
assert(result == VK_SUCCESS);
|
assert(result == VK_SUCCESS);
|
||||||
|
|
||||||
if (paused)
|
// Increment zoom
|
||||||
continue;
|
params.zoom *= 0.99;
|
||||||
|
|
||||||
for (int i = 0; i < (fastforward ? FASTFORWARD_RATE : 1); ++i) {
|
|
||||||
#ifdef JULIA_DTHETA
|
|
||||||
double complex julia = params.julia.re + I * params.julia.im;
|
|
||||||
julia *= julia_rotz;
|
|
||||||
params.julia.re = (float)creal(julia);
|
|
||||||
params.julia.im = (float)cimag(julia);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ZOOMRATE
|
|
||||||
params.scale *= (1 - ZOOMRATE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CPOW_DTHETA
|
|
||||||
double complex cpow = params.cpow.re + I * params.cpow.im;
|
|
||||||
cpow *= cpow_rotz;
|
|
||||||
params.cpow.re = (float)creal(cpow);
|
|
||||||
params.cpow.im = (float)cimag(cpow);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef POWRATE
|
|
||||||
params.zpow += POWRATE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vkDeviceWaitIdle(dev);
|
vkDeviceWaitIdle(dev);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user