diff --git a/frag_shader.glsl b/frag_shader.glsl index c3a56db..0cbac3b 100644 --- a/frag_shader.glsl +++ b/frag_shader.glsl @@ -4,15 +4,16 @@ */ #version 450 +#extension GL_ARB_gpu_shader_fp64 : enable #define MAXITER 1000 layout(location = 0) out vec4 out_colour; layout(push_constant) uniform Constants { - vec2 img_size; - vec2 shift; - float zoom; + dvec2 img_size; + dvec2 shift; + double zoom; } params; vec2 ss_offsets[4] = vec2[]( @@ -22,28 +23,31 @@ vec2 ss_offsets[4] = vec2[]( vec2( 0.25, 0.25) ); -vec2 maptoz(vec2 xy) +dvec2 maptoz(vec2 xy) { - return params.zoom * ((xy / params.img_size.xy) * 4.0 - 2.0) + params.shift; + dvec2 dxy = dvec2(xy); + dvec2 uv = ((dxy / params.img_size.xy) * 4.0LF - 2.0LF); + return params.zoom * uv + params.shift; } -float mandelbrot(vec2 c) { - vec2 z = vec2(0.0, 0.0); +double mandelbrot(dvec2 c) { + dvec2 z = dvec2(0.0LF, 0.0LF); for (int i = 0; i < MAXITER; ++i) { - z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + c; - if (length(z) > 2.0) - return float(i) / float(MAXITER); + z = dvec2(z.x * z.x - z.y * z.y, 2.0LF * z.x * z.y) + c; + if (length(z) > 2.0LF) + return double(i) / double(MAXITER); } return 0.0; } -vec3 colour(float i) { - return vec3(i, i * i, i * i * i); +vec3 colour(double i) { + float fi = float(i); + return vec3(fi, fi * fi, fi * fi * fi); } void main() { - vec2 c; + dvec2 c; vec3 col = vec3(0.0, 0.0, 0.0); for (int i = 0; i < 4; ++i) { c = maptoz(gl_FragCoord.xy + ss_offsets[i]); diff --git a/main.c b/main.c index b6007ca..5a9dcf5 100644 --- a/main.c +++ b/main.c @@ -24,11 +24,11 @@ #define MAX_SHADER_SIZE (4 * 1024) typedef struct { - float width, height; + double width, height; struct { - float x, y; + double x, y; } shift; - float zoom; + double zoom; } params_t; static const char *layers[] = { "VK_LAYER_KHRONOS_validation" }; @@ -101,6 +101,11 @@ int main(void) result = vkEnumeratePhysicalDevices(inst, &dev_count, &physical_dev); assert(result == VK_SUCCESS || result == VK_INCOMPLETE); + // Check that the device supports double precision + VkPhysicalDeviceFeatures features; + vkGetPhysicalDeviceFeatures(physical_dev, &features); + assert(features.shaderFloat64); + // Select queue family uint32_t queue_family_count = QUEUE_FAMILY_PROP_BUFFER_SIZE; VkQueueFamilyProperties @@ -131,12 +136,16 @@ int main(void) .queueCount = 1, .pQueuePriorities = &queue_priority, }; + const VkPhysicalDeviceFeatures enabled_features = { + .shaderFloat64 = VK_TRUE, + }; const VkDeviceCreateInfo dev_create_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pQueueCreateInfos = &queue_create_info, .queueCreateInfoCount = 1, .enabledExtensionCount = 1, .ppEnabledExtensionNames = &swapchain_ext_name, + .pEnabledFeatures = &enabled_features, }; VkDevice dev; result = vkCreateDevice(physical_dev, &dev_create_info, NULL, &dev); @@ -462,8 +471,8 @@ int main(void) assert(result == VK_SUCCESS); params_t params = { - .width = (float)swapchain_extent.width, - .height = (float)swapchain_extent.height, + .width = (double)swapchain_extent.width, + .height = (double)swapchain_extent.height, .shift = { .x = -0.743643887037158704752191506114774, .y = 0.131825904205311970493132056385139,