Remove implied length handling
[panamaz] / src / notzed.vulkan.test / classes / vulkan / test / TestSDF.java
1 /*
2 The MIT License (MIT)
3
4 Copyright (C) 2017 Eric Arneb├Ąck
5 Copyright (C) 2019 Michael Zucchi
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 THE SOFTWARE.
24
25  */
26
27  /*
28  * This is a Java conversion of a C conversion of this:
29  * https://github.com/Erkaman/vulkan_minimal_compute
30  *
31  * It's been simplified a bit and converted to the 'zvk' api.
32  */
33 package vulkan.test;
34
35 import au.notzed.display.Display;
36 import au.notzed.display.Event;
37 import au.notzed.display.Window;
38 import jdk.incubator.foreign.*;
39 import au.notzed.nativez.*;
40
41 import vulkan.*;
42 import static vulkan.Vulkan.*;
43
44 import static vulkan.test.GLMaths.*;
45
46 public class TestSDF {
47
48         static final boolean debug = true;
49
50         final static int NUM_SAMPLES = VK_SAMPLE_COUNT_1_BIT;
51         final static int NUM_DESCRIPTOR_SETS = 1;
52
53         ResourceScope scope = ResourceScope.newSharedScope();
54
55         int width = 800;
56         int height = 800;
57         float projection[] = new float[16];
58         float view[] = new float[16];
59         float model[] = new float[16];
60         float clip[] = new float[]{
61                 1.0f, 0.0f, 0.0f, 0.0f,
62                 0.0f, -1.0f, 0.0f, 0.0f,
63                 0.0f, 0.0f, 0.5f, 0.0f,
64                 0.0f, 0.0f, 0.5f, 1.0f
65         };
66         float mvp[] = new float[16];
67
68         VkInstance instance;
69         VkPhysicalDevice physicalDevice;
70         VkPhysicalDeviceMemoryProperties memory_properties;
71         VkPhysicalDeviceFeatures device_features;
72
73         int present_queue_index;
74         int graphics_queue_index;
75
76         VkDevice device;
77         VkSwapchainKHR chain;
78
79         VkQueue graphics_queue;
80         VkQueue present_queue;
81
82         int chainImageFormat;
83         HandleArray<VkImage> chainImage;
84         HandleArray<VkImageView> chainImageView;
85
86         int depthFormat;
87         VkImage depthImage;
88         VkImageView depthView;
89         VkDeviceMemory depthMemory;
90
91         VkCommandPool cmd_pool;
92         HandleArray<VkCommandBuffer> cmd;
93
94         BufferMemory uniform;
95         VkPipelineLayout pipeline_layout;
96
97         VkDescriptorSetLayout desc_layout;
98         VkDescriptorPool desc_pool;
99         HandleArray<VkDescriptorSet> desc_set;
100
101         VkRenderPass render_pass;
102         HandleArray<VkFramebuffer> framebuffers;
103
104         BufferMemory vertex;
105         HandleArray<VkBuffer> vertexBuffer = VkBuffer.createArray(1, (SegmentAllocator)scope);
106         VkVertexInputBindingDescription vi_binding = VkVertexInputBindingDescription.createArray(1, (SegmentAllocator)scope);
107         VkVertexInputAttributeDescription vi_attribs = VkVertexInputAttributeDescription.createArray(1, (SegmentAllocator)scope);
108
109         IntArray sdf_vs;
110         IntArray sdf_fs;
111         HandleArray<VkShaderModule> shader = VkShaderModule.createArray(2, (SegmentAllocator)scope);
112
113         HandleArray<VkPipeline> pipeline = VkPipeline.createArray(1, (SegmentAllocator)scope);
114
115         VkSemaphore chainSemaphore;
116         VkFence drawFence;
117
118         record BufferMemory(VkBuffer buffer, VkDeviceMemory memory, long size) {
119
120                 public void free(VkDevice device) {
121                         device.vkFreeMemory(memory);
122                         device.vkDestroyBuffer(buffer);
123                 }
124         }
125
126         VkDebugUtilsMessengerEXT logger;
127
128         void init_debug() throws Exception {
129                 if (!debug)
130                         return;
131                 try ( Frame frame = Frame.frame()) {
132                         var cb = PFN_vkDebugUtilsMessengerCallbackEXT.upcall((severity, flags, data) -> {
133                                 System.out.printf("Debug: %d: %s\n", severity, data.getMessage());
134                                 return 0;
135                         }, scope);
136                         VkDebugUtilsMessengerCreateInfoEXT info = VkDebugUtilsMessengerCreateInfoEXT.create(
137                                 0,
138                                 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
139                                 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
140                                 | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
141                                 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
142                                 cb,
143                                 null,
144                                 frame);
145
146                         logger = instance.vkCreateDebugUtilsMessengerEXT(info, scope);
147                 }
148
149                 //typedef VkBool32 (*PFN_vkDebugUtilsMessengerCallbackEXT)(VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *, void *);
150         }
151
152         void init_instance() throws Exception {
153                 try ( Frame frame = Frame.frame()) {
154                         VkInstanceCreateInfo info = VkInstanceCreateInfo.create(
155                                 0,
156                                 VkApplicationInfo.create("cube", 1, "cube-engine", 2, VK_API_VERSION_1_0, frame),
157                                 1, new String[]{"VK_LAYER_KHRONOS_validation"},
158                                 3, new String[]{"VK_KHR_surface", "VK_KHR_xlib_surface", "VK_EXT_debug_utils"},
159                                 frame
160                         );
161
162                         instance = VkInstance.vkCreateInstance(info, scope);
163                         System.out.printf("instance = %s\n", instance);
164                 }
165         }
166
167         Display display;
168         Window window;
169         VkSurfaceKHR surface;
170
171         void init_surface() throws Exception {
172                 display = Display.createX11Display();
173                 window = display.createWindow(width, height);
174                 surface = window.createVulkanSurface(instance, scope);
175                 System.out.printf("surface: %s\n", surface);
176         }
177
178         void init_device() throws Exception {
179                 try ( Frame frame = Frame.frame()) {
180                         IntArray count$h = IntArray.create(frame, 1);
181                         IntArray present$h = IntArray.create(frame, 1);
182                         HandleArray<VkPhysicalDevice> devs;
183                         int count;
184                         int res;
185
186                         devs = instance.vkEnumeratePhysicalDevices(frame, scope);
187
188                         // Search for device and queue indices
189                         int devid = -1;
190                         int present_queue = -1;
191                         int graphics_queue = -1;
192                         for (int i = 0; i < devs.length(); i++) {
193                                 VkPhysicalDevice dev = devs.getAtIndex(i);
194                                 VkQueueFamilyProperties famprops;
195
196                                 famprops = dev.vkGetPhysicalDeviceQueueFamilyProperties(frame);
197
198                                 for (int j = 0; j < famprops.length(); j++) {
199                                         boolean present;
200
201                                         dev.vkGetPhysicalDeviceSurfaceSupportKHR(j, surface, present$h);
202                                         present = present$h.get(0) != 0;
203
204                                         if (present && present_queue == -1)
205                                                 present_queue = j;
206                                         if ((famprops.getQueueFlagsAtIndex(j) & VK_QUEUE_GRAPHICS_BIT) != 0) {
207                                                 graphics_queue = j;
208                                                 if (present) {
209                                                         present_queue = j;
210                                                         break;
211                                                 }
212                                         }
213                                 }
214                                 if (present_queue != -1 && graphics_queue != -1) {
215                                         devid = i;
216                                         break;
217                                 }
218                         }
219
220                         if (devid == -1)
221                                 throw new Exception("Cannot find a suitable device");
222
223                         physicalDevice = devs.getAtIndex(devid);
224                         present_queue_index = present_queue;
225                         graphics_queue_index = graphics_queue;
226
227                         // NOTE: app scope
228                         memory_properties = VkPhysicalDeviceMemoryProperties.create((SegmentAllocator)scope);
229                         physicalDevice.vkGetPhysicalDeviceMemoryProperties(memory_properties);
230                         device_features = VkPhysicalDeviceFeatures.create((SegmentAllocator)scope);
231                         physicalDevice.vkGetPhysicalDeviceFeatures(device_features);
232
233                         FloatArray qpri = FloatArray.create(frame, 0.0f);
234                         VkDeviceQueueCreateInfo qinfo = VkDeviceQueueCreateInfo.create(
235                                 0,
236                                 graphics_queue,
237                                 1, qpri,
238                                 frame);
239                         String[] extensions = {
240                                 "VK_KHR_swapchain"
241                         };
242                         VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures.create(frame);
243                         features.setDepthClamp(1);
244                         VkDeviceCreateInfo devinfo = VkDeviceCreateInfo.create(
245                                 0,
246                                 1, qinfo,
247                                 0, null,
248                                 extensions.length, extensions,
249                                 features,
250                                 frame);
251
252                         device = physicalDevice.vkCreateDevice(devinfo, scope);
253
254                         System.out.printf("device = %s\n", device);
255
256                         /* ************************************************************** */
257                         int format;
258                         VkSurfaceFormatKHR surfFormats = physicalDevice.vkGetPhysicalDeviceSurfaceFormatsKHR(surface, frame);
259                         // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
260                         // the surface has no preferred format.  Otherwise, at least one
261                         // supported format will be returned.
262                         if (surfFormats.length() == 1 && surfFormats.getFormatAtIndex(0) == VK_FORMAT_UNDEFINED) {
263                                 format = VK_FORMAT_B8G8R8A8_UNORM;
264                         } else {
265                                 format = surfFormats.getFormatAtIndex(0);
266                         }
267
268                         VkSurfaceCapabilitiesKHR surfCapabilities = VkSurfaceCapabilitiesKHR.create(frame);
269
270                         physicalDevice.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(surface, surfCapabilities);
271                         IntArray presentModes = physicalDevice.vkGetPhysicalDeviceSurfacePresentModesKHR(surface, frame);
272
273                         VkExtent2D swapchainExtent;
274                         // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
275                         if (surfCapabilities.getCurrentExtent().getWidth() == 0xFFFFFFFF) {
276                                 // If the surface size is undefined, the size is set to
277                                 // the size of the images requested.
278                                 swapchainExtent = VkExtent2D.create(
279                                         clampi(width, surfCapabilities.getMinImageExtent().getWidth(), surfCapabilities.getMaxImageExtent().getWidth()),
280                                         clampi(height, surfCapabilities.getMinImageExtent().getHeight(), surfCapabilities.getMaxImageExtent().getHeight()),
281                                         frame);
282                         } else {
283                                 // If the surface size is defined, the swap chain size must match
284                                 swapchainExtent = surfCapabilities.getCurrentExtent();
285                         }
286                         int compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
287                         int compositeAlphaFlags[] = {
288                                 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
289                                 VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
290                                 VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
291                                 VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,};
292                         for (int flag: compositeAlphaFlags) {
293                                 if ((surfCapabilities.getSupportedCompositeAlpha() & flag) != 0) {
294                                         compositeAlpha = flag;
295                                         break;
296                                 }
297                         }
298
299                         VkSwapchainCreateInfoKHR chaininfo = VkSwapchainCreateInfoKHR.create(
300                                 0,
301                                 surface,
302                                 surfCapabilities.getMinImageCount(),
303                                 format,
304                                 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
305                                 swapchainExtent.getWidth(), swapchainExtent.getHeight(),
306                                 1, //.imageArrayLayers = 1,
307                                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
308                                 VK_SHARING_MODE_EXCLUSIVE,
309                                 // assumes queues are same.
310                                 0, null,
311                                 (surfCapabilities.getSupportedTransforms() & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) != 0
312                                 ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : surfCapabilities.getCurrentTransform(),
313                                 compositeAlpha,
314                                 VK_PRESENT_MODE_FIFO_KHR,
315                                 VK_TRUE,
316                                 null,
317                                 frame);
318
319                         chain = device.vkCreateSwapchainKHR(chaininfo, scope);
320
321                         int chainImageCount;
322
323                         chainImage = device.vkGetSwapchainImagesKHR(chain, (SegmentAllocator)scope);
324                         chainImageCount = (int)chainImage.length();
325                         chainImageView = VkImageView.createArray(chainImageCount, (SegmentAllocator)scope);
326
327                         VkImageViewCreateInfo viewinfo = VkImageViewCreateInfo.create(
328                                 0,
329                                 null,
330                                 VK_IMAGE_VIEW_TYPE_2D,
331                                 format,
332                                 frame);
333                         viewinfo.getComponents().set(VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A);
334                         viewinfo.getSubresourceRange().set(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
335
336                         for (int i = 0; i < chainImageCount; i++) {
337                                 viewinfo.setImage(chainImage.get(i));
338
339                                 chainImageView.setAtIndex(i, device.vkCreateImageView(viewinfo, scope));
340                         }
341
342                         chainImageFormat = format;
343                 }
344         }
345
346         void init_device_queue() {
347                 graphics_queue = device.vkGetDeviceQueue(graphics_queue_index, 0, scope);
348                 if (graphics_queue_index == present_queue_index) {
349                         present_queue = graphics_queue;
350                 } else {
351                         present_queue = device.vkGetDeviceQueue(present_queue_index, 0, scope);
352                 }
353         }
354
355         void init_command() throws Exception {
356                 try ( Frame frame = Frame.frame()) {
357                         VkCommandPoolCreateInfo poolinfo = VkCommandPoolCreateInfo.create(
358                                 0,
359                                 graphics_queue_index,
360                                 frame);
361
362                         cmd_pool = device.vkCreateCommandPool(poolinfo, scope);
363
364                         VkCommandBufferAllocateInfo cmdinfo = VkCommandBufferAllocateInfo.create(
365                                 cmd_pool,
366                                 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
367                                 1,
368                                 frame);
369
370                         cmd = device.vkAllocateCommandBuffers(cmdinfo, (SegmentAllocator)scope, scope);
371                 }
372         }
373
374         // parameterise as init_image?
375         void init_depth() throws Exception {
376                 try ( Frame frame = Frame.frame()) {
377                         int format = VK_FORMAT_D16_UNORM;
378                         VkMemoryRequirements req = VkMemoryRequirements.create(frame);
379                         VkImageCreateInfo imageinfo = VkImageCreateInfo.create(
380                                 0,
381                                 VK_IMAGE_TYPE_2D,
382                                 format,
383                                 width, height, 1,
384                                 1,
385                                 1,
386                                 NUM_SAMPLES,
387                                 0,
388                                 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
389                                 VK_SHARING_MODE_EXCLUSIVE,
390                                 0, null,
391                                 VK_IMAGE_LAYOUT_UNDEFINED,
392                                 frame);
393
394                         depthImage = device.vkCreateImage(imageinfo, scope);
395
396                         device.vkGetImageMemoryRequirements(depthImage, req);
397                         VkMemoryAllocateInfo alloc = VkMemoryAllocateInfo.create(
398                                 req.getSize(),
399                                 find_memory_type(memory_properties, req.getMemoryTypeBits(), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT),
400                                 frame);
401
402                         depthMemory = device.vkAllocateMemory(alloc, scope);
403
404                         device.vkBindImageMemory(depthImage, depthMemory, 0);
405
406                         VkImageViewCreateInfo viewinfo = VkImageViewCreateInfo.create(
407                                 0,
408                                 depthImage,
409                                 VK_IMAGE_VIEW_TYPE_2D,
410                                 VK_FORMAT_D16_UNORM,
411                                 frame);
412
413                         VkComponentMapping components = viewinfo.getComponents();
414                         components.setR(VK_COMPONENT_SWIZZLE_R);
415                         components.setG(VK_COMPONENT_SWIZZLE_G);
416                         components.setB(VK_COMPONENT_SWIZZLE_B);
417                         components.setA(VK_COMPONENT_SWIZZLE_A);
418                         VkImageSubresourceRange subresourceRange = viewinfo.getSubresourceRange();
419                         subresourceRange.setAspectMask(VK_IMAGE_ASPECT_DEPTH_BIT);
420                         subresourceRange.setLevelCount(1);
421                         subresourceRange.setLayerCount(1);
422
423                         depthView = device.vkCreateImageView(viewinfo, scope);
424
425                         depthFormat = format;
426                 }
427         }
428
429         void init_uniform() throws Exception {
430                 uniform = init_buffer(mvp.length * 4, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, MemorySegment.ofArray(mvp));
431         }
432
433         void init_descriptor() throws Exception {
434                 try ( Frame frame = Frame.frame()) {
435                         HandleArray<VkDescriptorSetLayout> layout_table = VkDescriptorSetLayout.createArray(1, frame);
436                         VkDescriptorSetLayoutBinding layout_binding = VkDescriptorSetLayoutBinding.create(
437                                 0,
438                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
439                                 1,
440                                 VK_SHADER_STAGE_VERTEX_BIT,
441                                 null,
442                                 frame);
443                         VkDescriptorSetLayoutCreateInfo descriptor_layout = VkDescriptorSetLayoutCreateInfo.create(
444                                 0,
445                                 1, layout_binding,
446                                 frame);
447
448                         desc_layout = device.vkCreateDescriptorSetLayout(descriptor_layout, scope);
449                         layout_table.setAtIndex(0, desc_layout);
450
451                         VkPipelineLayoutCreateInfo pipeline_info = VkPipelineLayoutCreateInfo.create(
452                                 0,
453                                 1, layout_table,
454                                 0, null,
455                                 frame);
456
457                         pipeline_layout = device.vkCreatePipelineLayout(pipeline_info, scope);
458
459                         VkDescriptorPoolSize type_count = VkDescriptorPoolSize.create(
460                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
461                                 1,
462                                 frame);
463
464                         VkDescriptorPoolCreateInfo descriptor_pool = VkDescriptorPoolCreateInfo.create(
465                                 0,
466                                 1,
467                                 1, type_count,
468                                 frame);
469
470                         desc_pool = device.vkCreateDescriptorPool(descriptor_pool, scope);
471
472                         VkDescriptorSetAllocateInfo alloc_info = VkDescriptorSetAllocateInfo.create(
473                                 desc_pool,
474                                 1, layout_table,
475                                 frame);
476
477                         System.out.println(alloc_info);
478
479                         desc_set = device.vkAllocateDescriptorSets(alloc_info, (SegmentAllocator)scope);
480
481                         VkDescriptorBufferInfo uniformInfo = VkDescriptorBufferInfo.create(uniform.buffer, 0, uniform.size, frame);
482                         VkWriteDescriptorSet writes = VkWriteDescriptorSet.create(
483                                 desc_set.getAtIndex(0),
484                                 0,
485                                 0,
486                                 1,
487                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
488                                 null,
489                                 uniformInfo,
490                                 null,
491                                 frame);
492
493                         device.vkUpdateDescriptorSets(1, writes, 0, null);
494                 }
495         }
496
497         void init_render() throws Exception {
498                 try ( Frame frame = Frame.frame()) {
499                         VkAttachmentDescription attachments = VkAttachmentDescription.createArray(2, frame);
500
501                         attachments.setFormat(chainImageFormat);
502                         attachments.setSamples(NUM_SAMPLES);
503                         attachments.setLoadOp(VK_ATTACHMENT_LOAD_OP_CLEAR);
504                         attachments.setStoreOp(VK_ATTACHMENT_STORE_OP_STORE);
505                         attachments.setStencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE);
506                         attachments.setStencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE);
507                         attachments.setInitialLayout(VK_IMAGE_LAYOUT_UNDEFINED);
508                         attachments.setFinalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
509                         attachments.setFlags(0);
510
511                         attachments.setFormatAtIndex(1, depthFormat);
512                         attachments.setSamplesAtIndex(1, NUM_SAMPLES);
513                         attachments.setLoadOpAtIndex(1, VK_ATTACHMENT_LOAD_OP_CLEAR);
514                         attachments.setStoreOpAtIndex(1, VK_ATTACHMENT_STORE_OP_STORE);
515                         attachments.setStencilLoadOpAtIndex(1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
516                         attachments.setStencilStoreOpAtIndex(1, VK_ATTACHMENT_STORE_OP_DONT_CARE);
517                         attachments.setInitialLayoutAtIndex(1, VK_IMAGE_LAYOUT_UNDEFINED);
518                         attachments.setFinalLayoutAtIndex(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
519                         attachments.setFlagsAtIndex(1, 0);
520
521                         VkAttachmentReference color_reference = VkAttachmentReference.create(
522                                 0,
523                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
524                                 frame);
525
526                         VkAttachmentReference depth_reference = VkAttachmentReference.create(
527                                 1,
528                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
529                                 frame);
530
531                         VkSubpassDescription subpass = VkSubpassDescription.create(
532                                 0,
533                                 VK_PIPELINE_BIND_POINT_GRAPHICS,
534                                 0, null,
535                                 1, color_reference,
536                                 null,
537                                 depth_reference,
538                                 0, null,
539                                 frame);
540
541                         VkRenderPassCreateInfo rp_info = VkRenderPassCreateInfo.create(
542                                 0,
543                                 2, attachments,
544                                 1, subpass,
545                                 0, null,
546                                 frame);
547
548                         render_pass = device.vkCreateRenderPass(rp_info, scope);
549                 }
550         }
551
552         void init_framebuffer() throws Exception {
553                 try ( Frame frame = Frame.frame()) {
554                         HandleArray<VkImageView> attachments = VkImageView.createArray(2, frame);
555
556                         attachments.setAtIndex(1, depthView);
557
558                         VkFramebufferCreateInfo fb_info = VkFramebufferCreateInfo.create(
559                                 0,
560                                 render_pass,
561                                 2, attachments,
562                                 width, height, 1,
563                                 frame);
564
565                         framebuffers = VkFramebuffer.createArray(chainImage.length(), (SegmentAllocator)scope);
566                         for (int i = 0; i < chainImage.size(); i++) {
567                                 attachments.setAtIndex(0, chainImageView.get(i));
568                                 framebuffers.setAtIndex(i, device.vkCreateFramebuffer(fb_info, scope));
569                                 System.out.printf("framebuffer[%d] = %s\n", i, framebuffers.getAtIndex(i));
570                         }
571                 }
572         }
573
574         void init_vertexbuffer() throws Exception {
575                 try ( Frame frame = Frame.frame()) {
576                         float[] image = {
577                                 -1, -1, 0, 1,
578                                 1, -1, 0, 1,
579                                 -1, 1, 0, 1,
580                                 -1, 1, 0, 1,
581                                 1, -1, 0, 1,
582                                 1, 1, 0, 1
583                         //      1, -1, 0, 1,
584                         //      -1, 1, 0, 1,
585                         //      1, 1, 0, 1
586                         };
587                         vertex = init_buffer(image.length * 4, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, MemorySegment.ofArray(image));
588
589                         vertexBuffer.setAtIndex(0, vertex.buffer);
590
591                         /* ***************************************** */
592                         vi_binding.setBinding(0);
593                         vi_binding.setInputRate(VK_VERTEX_INPUT_RATE_VERTEX);
594                         vi_binding.setStride(4 * 4);
595
596                         vi_attribs.setBinding(0);
597                         vi_attribs.setLocation(0);
598                         vi_attribs.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT);
599                         vi_attribs.setOffset(0);
600                         //vi_attribs.setBindingAtIndex(1, 0);
601                         //vi_attribs.setLocationAtIndex(1, 1);
602                         //vi_attribs.setFormatAtIndex(1, VK_FORMAT_R32G32B32A32_SFLOAT);
603                         //vi_attribs.setOffsetAtIndex(1, 16);
604                 }
605         }
606
607         void init_pipeline() throws Exception {
608                 int res;
609                 try ( Frame frame = Frame.frame()) {
610                         IntArray dynamicStateEnables = IntArray.create(frame,
611                                 VK_DYNAMIC_STATE_VIEWPORT,
612                                 VK_DYNAMIC_STATE_SCISSOR);
613
614                         VkPipelineDynamicStateCreateInfo dynamicState = VkPipelineDynamicStateCreateInfo.create(
615                                 0,
616                                 2, dynamicStateEnables,
617                                 frame);
618
619                         VkPipelineVertexInputStateCreateInfo vi = VkPipelineVertexInputStateCreateInfo.create(
620                                 0,
621                                 (int)vi_binding.length(), vi_binding,
622                                 (int)vi_attribs.length(), vi_attribs,
623                                 frame);
624
625                         VkPipelineInputAssemblyStateCreateInfo ia = VkPipelineInputAssemblyStateCreateInfo.create(
626                                 0,
627                                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
628                                 0,
629                                 frame);
630
631                         VkPipelineRasterizationStateCreateInfo rs = VkPipelineRasterizationStateCreateInfo.create(
632                                 0,
633                                 VK_TRUE,
634                                 VK_FALSE,
635                                 VK_POLYGON_MODE_FILL,
636                                 VK_CULL_MODE_BACK_BIT,
637                                 VK_FRONT_FACE_CLOCKWISE,
638                                 VK_FALSE,
639                                 0.0f,
640                                 0.0f,
641                                 0.0f,
642                                 1.0f,
643                                 frame);
644
645                         VkPipelineColorBlendAttachmentState att_state = VkPipelineColorBlendAttachmentState.create(
646                                 VK_FALSE,
647                                 VK_BLEND_FACTOR_ZERO,
648                                 VK_BLEND_FACTOR_ZERO,
649                                 VK_BLEND_OP_ADD,
650                                 VK_BLEND_FACTOR_ZERO,
651                                 VK_BLEND_FACTOR_ZERO,
652                                 VK_BLEND_OP_ADD,
653                                 0xf,
654                                 frame);
655
656                         VkPipelineColorBlendStateCreateInfo cb = VkPipelineColorBlendStateCreateInfo.create(
657                                 0,
658                                 VK_FALSE,
659                                 VK_LOGIC_OP_NO_OP,
660                                 1, att_state,
661                                 1.0f, 1.0f, 1.0f, 1.0f,
662                                 frame);
663
664                         VkPipelineViewportStateCreateInfo vp = VkPipelineViewportStateCreateInfo.create(
665                                 0,
666                                 1, null,
667                                 1, null,
668                                 frame);
669
670                         VkPipelineDepthStencilStateCreateInfo ds = VkPipelineDepthStencilStateCreateInfo.create(
671                                 0,
672                                 VK_TRUE,
673                                 VK_TRUE,
674                                 VK_COMPARE_OP_LESS_OR_EQUAL,
675                                 VK_FALSE,
676                                 VK_FALSE,
677                                 0.0f,
678                                 0.0f,
679                                 frame);
680                         VkStencilOpState back = ds.getBack();
681
682                         back.setFailOp(VK_STENCIL_OP_KEEP);
683                         back.setPassOp(VK_STENCIL_OP_KEEP);
684                         back.setCompareOp(VK_COMPARE_OP_ALWAYS);
685                         back.setCompareMask(0);
686                         back.setReference(0);
687                         back.setDepthFailOp(VK_STENCIL_OP_KEEP);
688                         back.setWriteMask(0);
689
690                         VkStencilOpState front = ds.getFront();
691
692                         front.setFailOp(VK_STENCIL_OP_KEEP);
693                         front.setPassOp(VK_STENCIL_OP_KEEP);
694                         front.setCompareOp(VK_COMPARE_OP_ALWAYS);
695                         front.setCompareMask(0);
696                         front.setReference(0);
697                         front.setDepthFailOp(VK_STENCIL_OP_KEEP);
698                         front.setWriteMask(0);
699
700                         VkPipelineMultisampleStateCreateInfo ms = VkPipelineMultisampleStateCreateInfo.create(
701                                 0,
702                                 NUM_SAMPLES,
703                                 0, //.sampleShadingEnable = VK_FALSE,
704                                 0.0f,
705                                 null,
706                                 0, //.alphaToCoverageEnable = VK_FALSE,
707                                 0, //.alphaToOneEnable = VK_FALSE,
708                                 frame
709                         );
710
711                         VkShaderModuleCreateInfo vsInfo = VkShaderModuleCreateInfo.create(
712                                 0,
713                                 sdf_vs.length() * 4,
714                                 sdf_vs,
715                                 frame);
716                         VkShaderModuleCreateInfo fsInfo = VkShaderModuleCreateInfo.create(
717                                 0,
718                                 sdf_fs.length() * 4,
719                                 sdf_fs,
720                                 frame);
721
722                         shader.setAtIndex(0, device.vkCreateShaderModule(vsInfo, scope));
723                         shader.setAtIndex(1, device.vkCreateShaderModule(fsInfo, scope));
724
725                         VkPipelineShaderStageCreateInfo shaderStages = VkPipelineShaderStageCreateInfo.createArray(2, (SegmentAllocator)scope);
726
727                         shaderStages.setStage(VK_SHADER_STAGE_VERTEX_BIT);
728                         shaderStages.setName("main", (SegmentAllocator)scope);
729                         shaderStages.setModule(shader.get(0));
730
731                         shaderStages.setStageAtIndex(1, VK_SHADER_STAGE_FRAGMENT_BIT);
732                         shaderStages.setNameAtIndex(1, "main", (SegmentAllocator)scope);
733                         shaderStages.setModuleAtIndex(1, shader.get(1));
734
735                         VkGraphicsPipelineCreateInfo pipeline = VkGraphicsPipelineCreateInfo.create(
736                                 0,
737                                 2, shaderStages,
738                                 vi,
739                                 ia,
740                                 null,
741                                 vp,
742                                 rs,
743                                 ms,
744                                 ds,
745                                 cb,
746                                 dynamicState,
747                                 pipeline_layout,
748                                 render_pass,
749                                 0,
750                                 null,
751                                 0,
752                                 frame);
753
754                         res = device.vkCreateGraphicsPipelines(null, 1, pipeline, this.pipeline);
755
756                         VkSemaphoreCreateInfo seminfo = VkSemaphoreCreateInfo.create(0, frame);
757                         chainSemaphore = device.vkCreateSemaphore(seminfo, scope);
758
759                         VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.create(0, frame);
760                         drawFence = device.vkCreateFence(fenceInfo, scope);
761                 }
762         }
763
764         void execute_begin_command_buffer() throws Exception {
765                 /* DEPENDS on init_command() */
766                 try ( Frame frame = Frame.frame()) {
767                         VkCommandBufferBeginInfo cmd_buf_info = VkCommandBufferBeginInfo.create(
768                                 0,
769                                 null,
770                                 frame);
771
772                         cmd.getAtIndex(0).vkBeginCommandBuffer(cmd_buf_info);
773                 }
774         }
775
776         void execute_end_command_buffer() throws Exception {
777                 cmd.getAtIndex(0).vkEndCommandBuffer();
778         }
779
780         final static long FENCE_TIMEOUT = 100000000;
781
782         void execute_queue_command_buffer() throws Exception {
783                 int res;
784
785                 /* Queue the command buffer for execution */
786  /* FIXME: frame shoudl provide or take explicit scope */
787                 try ( ResourceScope scope = ResourceScope.newConfinedScope();  Frame frame = Frame.frame()) {
788                         IntArray pipe_stage_flags = IntArray.create(frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
789                         VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.create(0, frame);
790                         HandleArray<VkFence> fences = VkFence.createArray(1, frame);
791
792                         fences.setAtIndex(0, device.vkCreateFence(fenceInfo, scope));
793
794                         VkSubmitInfo submit_info = VkSubmitInfo.create(
795                                 1, null, pipe_stage_flags,
796                                 (int)cmd.length(), cmd,
797                                 0, null,
798                                 frame);
799
800                         graphics_queue.vkQueueSubmit(1, submit_info, drawFence);
801
802                         do {
803                                 res = device.vkWaitForFences(1, fences, 1, FENCE_TIMEOUT);
804                         } while (res == VK_TIMEOUT);
805
806                         device.vkDestroyFence(fences.getAtIndex(0));
807                 }
808         }
809
810         void cmd_viewport() {
811                 try ( Frame frame = Frame.frame()) {
812                         VkCommandBuffer cmd = this.cmd.getAtIndex(0);
813                         VkViewport viewport = VkViewport.create(
814                                 0, 0, width, height, 0.0f, 1.0f,
815                                 frame);
816                         cmd.vkCmdSetViewport(0, 1, viewport);
817                 }
818         }
819
820         void cmd_scissors() {
821                 try ( Frame frame = Frame.frame()) {
822                         VkCommandBuffer cmd = this.cmd.getAtIndex(0);
823                         VkRect2D scissor = VkRect2D.create(frame);
824                         VkExtent2D extent = scissor.getExtent();
825
826                         extent.setWidth(width);
827                         extent.setHeight(height);
828
829                         cmd.vkCmdSetScissor(0, 1, scissor);
830                 }
831         }
832
833         void cmd_paint() throws Exception {
834                 int res;
835                 try ( Frame frame = Frame.frame()) {
836                         int chainIndex;
837                         IntArray chainIndices = IntArray.createArray(1, frame);
838                         VkCommandBuffer cmd = this.cmd.getAtIndex(0);
839
840                         device.vkAcquireNextImageKHR(chain, ~0L, chainSemaphore, null, chainIndices);
841                         chainIndex = chainIndices.getAtIndex(0);
842                         LongArray offsets = LongArray.createArray(1, frame);
843
844                         VkClearValue clear_values = VkClearValue.createArray(2, frame);
845                         clear_values.getColor().setFloat32(0.2f, 0.2f, 0.2f, 0.2f);
846                         VkClearDepthStencilValue depthStencil = clear_values.getAtIndex(1).getDepthStencil();
847                         depthStencil.setDepth(1.0f);
848                         depthStencil.setStencil(0);
849
850                         System.out.printf("render framebuffer[%d] = %s\n", chainIndex, framebuffers.getAtIndex(chainIndex));
851
852                         VkRenderPassBeginInfo rp_begin = VkRenderPassBeginInfo.create(
853                                 render_pass,
854                                 framebuffers.getAtIndex(chainIndex),
855                                 0, 0, width, height,
856                                 2, clear_values,
857                                 frame);
858
859                         cmd.vkCmdBeginRenderPass(rp_begin, VK_SUBPASS_CONTENTS_INLINE);
860
861                         cmd.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getAtIndex(0));
862                         cmd.vkCmdBindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, NUM_DESCRIPTOR_SETS, desc_set, 0, null);
863                         cmd.vkCmdBindVertexBuffers(0, 1, vertexBuffer, offsets);
864
865                         cmd_viewport();
866                         cmd_scissors();
867
868                         cmd.vkCmdDraw(12 * 3, 1, 0, 0);
869                         cmd.vkCmdEndRenderPass();
870
871                         cmd.vkEndCommandBuffer();
872
873                         IntArray pipe_stage_flags = IntArray.create(frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
874                         HandleArray<VkSemaphore> semaphores = VkSemaphore.createArray(1, frame);//, chainSemaphore, scope);
875
876                         semaphores.setAtIndex(0, chainSemaphore);
877
878                         VkSubmitInfo submit_info = VkSubmitInfo.create(
879                                 1, semaphores, pipe_stage_flags,
880                                 (int)this.cmd.length(), this.cmd,
881                                 0, null,
882                                 frame);
883
884                         HandleArray<VkFence> fences = VkFence.createArray(1, frame);
885
886                         fences.setAtIndex(0, drawFence);
887
888                         // Queue the command buffer for execution
889                         device.vkResetFences(1, fences);
890
891                         graphics_queue.vkQueueSubmit(1, submit_info, drawFence);
892
893                         // Make sure command buffer is finished before presenting
894                         do {
895                                 res = device.vkWaitForFences(1, fences, VK_TRUE, FENCE_TIMEOUT);
896                         } while (res == VK_TIMEOUT);
897
898                         // Now present the image in the window
899                         HandleArray<VkSwapchainKHR> chains = VkSwapchainKHR.createArray(1, frame);
900                         chains.setAtIndex(0, chain);
901                         VkPresentInfoKHR present = VkPresentInfoKHR.create(
902                                 0, null,
903                                 1, chains, chainIndices, null,
904                                 frame);
905
906                         present_queue.vkQueuePresentKHR(present);
907                 }
908         }
909
910         /**
911          * Buffers are created in three steps:
912          * 1) create buffer, specifying usage and size
913          * 2) allocate memory based on memory requirements
914          * 3) bind memory
915          * <p>
916          */
917         BufferMemory init_buffer(long dataSize, int usage, int properties, MemorySegment init) throws Exception {
918                 try ( Frame frame = Frame.frame()) {
919                         VkMemoryRequirements req = VkMemoryRequirements.create(frame);
920                         VkBufferCreateInfo buf_info = VkBufferCreateInfo.create(
921                                 0,
922                                 dataSize,
923                                 usage,
924                                 VK_SHARING_MODE_EXCLUSIVE,
925                                 0, null,
926                                 frame);
927
928                         VkBuffer buffer = device.vkCreateBuffer(buf_info, scope);
929
930                         device.vkGetBufferMemoryRequirements(buffer, req);
931
932                         VkMemoryAllocateInfo alloc = VkMemoryAllocateInfo.create(
933                                 req.getSize(),
934                                 find_memory_type(memory_properties, req.getMemoryTypeBits(), properties),
935                                 frame);
936
937                         VkDeviceMemory memory = device.vkAllocateMemory(alloc, scope);
938
939                         if (init != null) {
940                                 MemorySegment mem = device.vkMapMemory(memory, 0, dataSize, 0, scope);
941                                 mem.copyFrom(init);
942                                 device.vkUnmapMemory(memory);
943                         }
944
945                         device.vkBindBufferMemory(buffer, memory, 0);
946
947                         return new BufferMemory(buffer, memory, dataSize);
948                 }
949         }
950
951         void shutdown() {
952                 device.vkDestroyFence(drawFence);
953                 device.vkDestroySemaphore(chainSemaphore);
954
955                 device.vkDestroyPipeline(pipeline.getAtIndex(0));
956                 for (int i = 0; i < shader.size(); i++)
957                         device.vkDestroyShaderModule(shader.getAtIndex(i));
958
959                 vertex.free(device);
960                 uniform.free(device);
961
962                 for (int i = 0; i < framebuffers.size(); i++)
963                         device.vkDestroyFramebuffer(framebuffers.getAtIndex(i));
964
965                 device.vkDestroyRenderPass(render_pass);
966
967                 device.vkDestroyDescriptorPool(desc_pool);
968                 device.vkDestroyPipelineLayout(pipeline_layout);
969                 device.vkDestroyDescriptorSetLayout(desc_layout);
970
971                 device.vkDestroyImageView(depthView);
972                 device.vkFreeMemory(depthMemory);
973                 device.vkDestroyImage(depthImage);
974
975                 for (int i = 0; i < chainImageView.size(); i++)
976                         device.vkDestroyImageView(chainImageView.getAtIndex(i));
977
978                 device.vkDestroySwapchainKHR(chain);
979
980                 device.vkDestroyCommandPool(cmd_pool);
981                 device.vkDestroyDevice();
982
983                 instance.vkDestroySurfaceKHR(surface);
984                 window.close();
985                 display.close();
986
987                 if (logger != null)
988                         instance.vkDestroyDebugUtilsMessengerEXT(logger);
989                 instance.vkDestroyInstance();
990         }
991
992         /**
993          * This finds the memory type index for the memory on a specific device.
994          */
995         static int find_memory_type(VkPhysicalDeviceMemoryProperties memory, int typeMask, int query) {
996                 VkMemoryType mtypes = memory.getMemoryTypes();
997
998                 for (int i = 0; i < memory.getMemoryTypeCount(); i++) {
999                         if (((1 << i) & typeMask) != 0 && ((mtypes.getAtIndex(i).getPropertyFlags() & query) == query))
1000                                 return i;
1001                 }
1002                 return -1;
1003         }
1004
1005         static int clampi(int v, int min, int max) {
1006                 return v < min ? min : v < max ? v : max;
1007         }
1008
1009         void init_matrices() {
1010                 //float eye[] = new float[] {-5, 3, -10};
1011                 float eye[] = new float[]{0, 0, -10};
1012                 float centre[] = new float[]{0, 0, 0};
1013                 float up[] = new float[]{0, -1, 0};
1014                 float t0[] = new float[16], t1[] = new float[16];
1015
1016                 perspective(projection, (float)(Math.PI * 0.25), 1.0f, 0.1f, 100.0f);
1017                 lookAt(view, eye, centre, up);
1018                 identity4f(model);
1019                 mult4x4f(t0, clip, projection);
1020                 mult4x4f(t1, t0, view);
1021                 mult4x4f(mvp, t1, model);
1022         }
1023
1024         void demo() throws Exception {
1025                 sdf_vs = ShaderIO.loadSdf_vs((SegmentAllocator)scope);
1026                 sdf_fs = ShaderIO.loadSdf_fs((SegmentAllocator)scope);
1027
1028                 init_matrices();
1029
1030                 init_instance();
1031                 init_debug();
1032
1033                 init_surface();
1034                 init_device();
1035                 init_device_queue();
1036                 init_command();
1037                 init_depth();
1038                 init_uniform();
1039
1040                 init_descriptor();
1041                 init_render();
1042                 init_framebuffer();
1043                 init_vertexbuffer();
1044                 init_pipeline();
1045
1046                 execute_begin_command_buffer();
1047
1048                 cmd_paint();
1049
1050                 System.out.println("Any key to quit");
1051                 Event e;
1052 outer:  while ((e = window.nextEvent(true)) != null) {
1053                         switch (e.type) {
1054                         case Event.KEY:
1055                         case Event.CLOSE:
1056                                 break outer;
1057                         }
1058                 }
1059
1060                 shutdown();
1061         }
1062
1063         public static void main(String[] args) throws Throwable {
1064                 System.loadLibrary("vulkan");
1065                 System.loadLibrary("X11");
1066
1067                 new TestSDF().demo();
1068         }
1069 }