4 Copyright (C) 2017 Eric Arnebäck
5 Copyright (C) 2019 Michael Zucchi
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:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
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
28 * This is a Java conversion of a C conversion of this:
29 * https://github.com/Erkaman/vulkan_minimal_compute
31 * It's been simplified a bit and converted to the 'zvk' api.
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.*;
42 import static vulkan.Vulkan.*;
44 import static vulkan.test.GLMaths.*;
46 public class TestSDF {
48 static final boolean debug = true;
50 final static int NUM_SAMPLES = VK_SAMPLE_COUNT_1_BIT;
51 final static int NUM_DESCRIPTOR_SETS = 1;
53 ResourceScope scope = ResourceScope.newSharedScope();
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
66 float mvp[] = new float[16];
69 VkPhysicalDevice physicalDevice;
70 VkPhysicalDeviceMemoryProperties memory_properties;
71 VkPhysicalDeviceFeatures device_features;
73 int present_queue_index;
74 int graphics_queue_index;
79 VkQueue graphics_queue;
80 VkQueue present_queue;
83 HandleArray<VkImage> chainImage;
84 HandleArray<VkImageView> chainImageView;
88 VkImageView depthView;
89 VkDeviceMemory depthMemory;
91 VkCommandPool cmd_pool;
92 HandleArray<VkCommandBuffer> cmd;
95 VkPipelineLayout pipeline_layout;
97 VkDescriptorSetLayout desc_layout;
98 VkDescriptorPool desc_pool;
99 HandleArray<VkDescriptorSet> desc_set;
101 VkRenderPass render_pass;
102 HandleArray<VkFramebuffer> framebuffers;
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);
111 HandleArray<VkShaderModule> shader = VkShaderModule.createArray(2, (SegmentAllocator)scope);
113 HandleArray<VkPipeline> pipeline = VkPipeline.createArray(1, (SegmentAllocator)scope);
115 VkSemaphore chainSemaphore;
118 record BufferMemory(VkBuffer buffer, VkDeviceMemory memory, long size) {
120 public void free(VkDevice device) {
121 device.vkFreeMemory(memory);
122 device.vkDestroyBuffer(buffer);
126 VkDebugUtilsMessengerEXT logger;
128 void init_debug() throws Exception {
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());
136 VkDebugUtilsMessengerCreateInfoEXT info = VkDebugUtilsMessengerCreateInfoEXT.create(frame,
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,
145 logger = instance.vkCreateDebugUtilsMessengerEXT(info, scope);
148 //typedef VkBool32 (*PFN_vkDebugUtilsMessengerCallbackEXT)(VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *, void *);
151 void init_instance() throws Exception {
152 try ( Frame frame = Frame.frame()) {
153 VkInstanceCreateInfo info = VkInstanceCreateInfo.create(frame,
155 VkApplicationInfo.create(frame, "cube", 1, "cube-engine", 2, VK_API_VERSION_1_0),
156 new String[]{"VK_LAYER_KHRONOS_validation"},
157 new String[]{"VK_KHR_surface", "VK_KHR_xlib_surface", "VK_EXT_debug_utils"}
160 instance = VkInstance.vkCreateInstance(info, scope);
161 System.out.printf("instance = %s\n", instance);
167 VkSurfaceKHR surface;
169 void init_surface() throws Exception {
170 display = Display.createX11Display();
171 window = display.createWindow(width, height);
172 surface = window.createVulkanSurface(instance, scope);
173 System.out.printf("surface: %s\n", surface);
176 void init_device() throws Exception {
177 try ( Frame frame = Frame.frame()) {
178 IntArray count$h = IntArray.create(frame, 1);
179 IntArray present$h = IntArray.create(frame, 1);
180 HandleArray<VkPhysicalDevice> devs;
184 devs = instance.vkEnumeratePhysicalDevices(frame, scope);
186 // Search for device and queue indices
188 int present_queue = -1;
189 int graphics_queue = -1;
190 for (int i = 0; i < devs.length(); i++) {
191 VkPhysicalDevice dev = devs.getAtIndex(i);
192 VkQueueFamilyProperties famprops;
194 famprops = dev.vkGetPhysicalDeviceQueueFamilyProperties(frame);
196 for (int j = 0; j < famprops.length(); j++) {
199 dev.vkGetPhysicalDeviceSurfaceSupportKHR(j, surface, present$h);
200 present = present$h.get(0) != 0;
202 if (present && present_queue == -1)
204 if ((famprops.getQueueFlagsAtIndex(j) & VK_QUEUE_GRAPHICS_BIT) != 0) {
212 if (present_queue != -1 && graphics_queue != -1) {
219 throw new Exception("Cannot find a suitable device");
221 physicalDevice = devs.getAtIndex(devid);
222 present_queue_index = present_queue;
223 graphics_queue_index = graphics_queue;
226 memory_properties = VkPhysicalDeviceMemoryProperties.create((SegmentAllocator)scope);
227 physicalDevice.vkGetPhysicalDeviceMemoryProperties(memory_properties);
228 device_features = VkPhysicalDeviceFeatures.create((SegmentAllocator)scope);
229 physicalDevice.vkGetPhysicalDeviceFeatures(device_features);
231 FloatArray qpri = FloatArray.create(frame, 0.0f);
232 VkDeviceQueueCreateInfo qinfo = VkDeviceQueueCreateInfo.create(
237 String[] extensions = {
240 VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures.create(frame);
241 features.setDepthClamp(1);
242 VkDeviceCreateInfo devinfo = VkDeviceCreateInfo.create(
250 device = physicalDevice.vkCreateDevice(devinfo, scope);
252 System.out.printf("device = %s\n", device);
254 /* ************************************************************** */
256 VkSurfaceFormatKHR surfFormats = physicalDevice.vkGetPhysicalDeviceSurfaceFormatsKHR(surface, frame);
257 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
258 // the surface has no preferred format. Otherwise, at least one
259 // supported format will be returned.
260 if (surfFormats.length() == 1 && surfFormats.getFormatAtIndex(0) == VK_FORMAT_UNDEFINED) {
261 format = VK_FORMAT_B8G8R8A8_UNORM;
263 format = surfFormats.getFormatAtIndex(0);
266 VkSurfaceCapabilitiesKHR surfCapabilities = VkSurfaceCapabilitiesKHR.create(frame);
268 physicalDevice.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(surface, surfCapabilities);
269 IntArray presentModes = physicalDevice.vkGetPhysicalDeviceSurfacePresentModesKHR(surface, frame);
271 VkExtent2D swapchainExtent;
272 // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
273 if (surfCapabilities.getCurrentExtent().getWidth() == 0xFFFFFFFF) {
274 // If the surface size is undefined, the size is set to
275 // the size of the images requested.
276 swapchainExtent = VkExtent2D.create(frame,
277 clampi(width, surfCapabilities.getMinImageExtent().getWidth(), surfCapabilities.getMaxImageExtent().getWidth()),
278 clampi(height, surfCapabilities.getMinImageExtent().getHeight(), surfCapabilities.getMaxImageExtent().getHeight()));
280 // If the surface size is defined, the swap chain size must match
281 swapchainExtent = surfCapabilities.getCurrentExtent();
283 int compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
284 int compositeAlphaFlags[] = {
285 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
286 VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
287 VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
288 VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,};
289 for (int flag: compositeAlphaFlags) {
290 if ((surfCapabilities.getSupportedCompositeAlpha() & flag) != 0) {
291 compositeAlpha = flag;
296 VkSwapchainCreateInfoKHR chaininfo = VkSwapchainCreateInfoKHR.create(frame,
299 surfCapabilities.getMinImageCount(),
301 VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
302 1, //.imageArrayLayers = 1,
303 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
304 VK_SHARING_MODE_EXCLUSIVE,
305 // assumes queues are same.
307 (surfCapabilities.getSupportedTransforms() & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) != 0
308 ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : surfCapabilities.getCurrentTransform(),
310 VK_PRESENT_MODE_FIFO_KHR,
313 chaininfo.getImageExtent().setWidth(swapchainExtent.getWidth());
314 chaininfo.getImageExtent().setHeight(swapchainExtent.getHeight());
316 chain = device.vkCreateSwapchainKHR(chaininfo, scope);
320 chainImage = device.vkGetSwapchainImagesKHR(chain, (SegmentAllocator)scope);
321 chainImageCount = (int)chainImage.length();
322 chainImageView = VkImageView.createArray(chainImageCount, (SegmentAllocator)scope);
324 VkImageViewCreateInfo viewinfo = VkImageViewCreateInfo.create(frame,
327 VK_IMAGE_VIEW_TYPE_2D,
329 VkComponentMapping components = viewinfo.getComponents();
330 components.setR(VK_COMPONENT_SWIZZLE_R);
331 components.setG(VK_COMPONENT_SWIZZLE_G);
332 components.setB(VK_COMPONENT_SWIZZLE_B);
333 components.setA(VK_COMPONENT_SWIZZLE_A);
334 VkImageSubresourceRange subresourceRange = viewinfo.getSubresourceRange();
335 subresourceRange.setAspectMask(VK_IMAGE_ASPECT_COLOR_BIT);
336 subresourceRange.setLevelCount(1);
337 subresourceRange.setLayerCount(1);
339 for (int i = 0; i < chainImageCount; i++) {
340 viewinfo.setImage(chainImage.get(i));
342 chainImageView.setAtIndex(i, device.vkCreateImageView(viewinfo, scope));
345 chainImageFormat = format;
349 void init_device_queue() {
350 graphics_queue = device.vkGetDeviceQueue(graphics_queue_index, 0, scope);
351 if (graphics_queue_index == present_queue_index) {
352 present_queue = graphics_queue;
354 present_queue = device.vkGetDeviceQueue(present_queue_index, 0, scope);
358 void init_command() throws Exception {
359 try ( Frame frame = Frame.frame()) {
360 VkCommandPoolCreateInfo poolinfo = VkCommandPoolCreateInfo.create(frame,
362 graphics_queue_index);
364 cmd_pool = device.vkCreateCommandPool(poolinfo, scope);
366 VkCommandBufferAllocateInfo cmdinfo = VkCommandBufferAllocateInfo.create(frame,
368 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
371 cmd = device.vkAllocateCommandBuffers(cmdinfo, (SegmentAllocator)scope, scope);
375 // parameterise as init_image?
376 void init_depth() throws Exception {
377 try ( Frame frame = Frame.frame()) {
378 int format = VK_FORMAT_D16_UNORM;
379 VkMemoryRequirements req = VkMemoryRequirements.create(frame);
380 VkImageCreateInfo imageinfo = VkImageCreateInfo.create(frame, 0,
387 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
388 VK_SHARING_MODE_EXCLUSIVE,
390 VK_IMAGE_LAYOUT_UNDEFINED);
391 imageinfo.getExtent().setWidth(width);
392 imageinfo.getExtent().setHeight(height);
393 imageinfo.getExtent().setDepth(1);
395 depthImage = device.vkCreateImage(imageinfo, scope);
397 device.vkGetImageMemoryRequirements(depthImage, req);
398 VkMemoryAllocateInfo alloc = VkMemoryAllocateInfo.create(frame,
400 find_memory_type(memory_properties, req.getMemoryTypeBits(), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
402 depthMemory = device.vkAllocateMemory(alloc, scope);
404 device.vkBindImageMemory(depthImage, depthMemory, 0);
406 VkImageViewCreateInfo viewinfo = VkImageViewCreateInfo.create(frame, 0,
408 VK_IMAGE_VIEW_TYPE_2D,
409 VK_FORMAT_D16_UNORM);
411 VkComponentMapping components = viewinfo.getComponents();
412 components.setR(VK_COMPONENT_SWIZZLE_R);
413 components.setG(VK_COMPONENT_SWIZZLE_G);
414 components.setB(VK_COMPONENT_SWIZZLE_B);
415 components.setA(VK_COMPONENT_SWIZZLE_A);
416 VkImageSubresourceRange subresourceRange = viewinfo.getSubresourceRange();
417 subresourceRange.setAspectMask(VK_IMAGE_ASPECT_DEPTH_BIT);
418 subresourceRange.setLevelCount(1);
419 subresourceRange.setLayerCount(1);
421 depthView = device.vkCreateImageView(viewinfo, scope);
423 depthFormat = format;
427 void init_uniform() throws Exception {
428 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 void init_descriptor() throws Exception {
432 try ( Frame frame = Frame.frame()) {
433 HandleArray<VkDescriptorSetLayout> layout_table = VkDescriptorSetLayout.createArray(1, frame);
434 VkDescriptorSetLayoutBinding layout_binding = VkDescriptorSetLayoutBinding.create(frame,
436 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
438 VK_SHADER_STAGE_VERTEX_BIT,
440 VkDescriptorSetLayoutCreateInfo descriptor_layout = VkDescriptorSetLayoutCreateInfo.create(frame,
444 desc_layout = device.vkCreateDescriptorSetLayout(descriptor_layout, scope);
445 layout_table.setAtIndex(0, desc_layout);
447 VkPipelineLayoutCreateInfo pipeline_info = VkPipelineLayoutCreateInfo.create(frame,
453 pipeline_layout = device.vkCreatePipelineLayout(pipeline_info, scope);
455 VkDescriptorPoolSize type_count = VkDescriptorPoolSize.create(frame,
456 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
459 VkDescriptorPoolCreateInfo descriptor_pool = VkDescriptorPoolCreateInfo.create(frame,
464 desc_pool = device.vkCreateDescriptorPool(descriptor_pool, scope);
466 VkDescriptorSetAllocateInfo alloc_info = VkDescriptorSetAllocateInfo.create(frame,
471 System.out.println(alloc_info);
473 desc_set = device.vkAllocateDescriptorSets(alloc_info, (SegmentAllocator)scope);
475 VkDescriptorBufferInfo uniformInfo = VkDescriptorBufferInfo.create(frame, uniform.buffer, 0, uniform.size);
476 VkWriteDescriptorSet writes = VkWriteDescriptorSet.create(frame,
477 desc_set.getAtIndex(0),
481 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
486 device.vkUpdateDescriptorSets(1, writes, 0, null);
490 void init_render() throws Exception {
491 try ( Frame frame = Frame.frame()) {
492 VkAttachmentDescription attachments = VkAttachmentDescription.createArray(2, frame);
494 attachments.setFormat(chainImageFormat);
495 attachments.setSamples(NUM_SAMPLES);
496 attachments.setLoadOp(VK_ATTACHMENT_LOAD_OP_CLEAR);
497 attachments.setStoreOp(VK_ATTACHMENT_STORE_OP_STORE);
498 attachments.setStencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE);
499 attachments.setStencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE);
500 attachments.setInitialLayout(VK_IMAGE_LAYOUT_UNDEFINED);
501 attachments.setFinalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
502 attachments.setFlags(0);
504 attachments.setFormatAtIndex(1, depthFormat);
505 attachments.setSamplesAtIndex(1, NUM_SAMPLES);
506 attachments.setLoadOpAtIndex(1, VK_ATTACHMENT_LOAD_OP_CLEAR);
507 attachments.setStoreOpAtIndex(1, VK_ATTACHMENT_STORE_OP_STORE);
508 attachments.setStencilLoadOpAtIndex(1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
509 attachments.setStencilStoreOpAtIndex(1, VK_ATTACHMENT_STORE_OP_DONT_CARE);
510 attachments.setInitialLayoutAtIndex(1, VK_IMAGE_LAYOUT_UNDEFINED);
511 attachments.setFinalLayoutAtIndex(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
512 attachments.setFlagsAtIndex(1, 0);
514 VkAttachmentReference color_reference = VkAttachmentReference.create(frame,
516 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
518 VkAttachmentReference depth_reference = VkAttachmentReference.create(frame,
520 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
522 VkSubpassDescription subpass = VkSubpassDescription.create(frame,
524 VK_PIPELINE_BIND_POINT_GRAPHICS,
532 VkRenderPassCreateInfo rp_info = VkRenderPassCreateInfo.create(frame,
534 //(int)attachments.length(),
539 render_pass = device.vkCreateRenderPass(rp_info, scope);
543 void init_framebuffer() throws Exception {
544 try ( Frame frame = Frame.frame()) {
545 HandleArray<VkImageView> attachments = VkImageView.createArray(2, frame);
547 attachments.setAtIndex(1, depthView);
549 // FIXME: I don't think i want lenghts implied for types tbh
550 VkFramebufferCreateInfo fb_info = VkFramebufferCreateInfo.create(frame,
559 framebuffers = VkFramebuffer.createArray(chainImage.length(), (SegmentAllocator)scope);
560 for (int i = 0; i < chainImage.size(); i++) {
561 attachments.setAtIndex(0, chainImageView.get(i));
562 framebuffers.setAtIndex(i, device.vkCreateFramebuffer(fb_info, scope));
563 System.out.printf("framebuffer[%d] = %s\n", i, framebuffers.getAtIndex(i));
568 void init_vertexbuffer() throws Exception {
569 try ( Frame frame = Frame.frame()) {
581 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));
583 vertexBuffer.setAtIndex(0, vertex.buffer);
585 /* ***************************************** */
586 vi_binding.setBinding(0);
587 vi_binding.setInputRate(VK_VERTEX_INPUT_RATE_VERTEX);
588 vi_binding.setStride(4 * 4);
590 vi_attribs.setBinding(0);
591 vi_attribs.setLocation(0);
592 vi_attribs.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT);
593 vi_attribs.setOffset(0);
594 //vi_attribs.setBindingAtIndex(1, 0);
595 //vi_attribs.setLocationAtIndex(1, 1);
596 //vi_attribs.setFormatAtIndex(1, VK_FORMAT_R32G32B32A32_SFLOAT);
597 //vi_attribs.setOffsetAtIndex(1, 16);
601 void init_pipeline() throws Exception {
603 try ( Frame frame = Frame.frame()) {
604 IntArray dynamicStateEnables = IntArray.create(frame,
605 VK_DYNAMIC_STATE_VIEWPORT,
606 VK_DYNAMIC_STATE_SCISSOR);
608 VkPipelineDynamicStateCreateInfo dynamicState = VkPipelineDynamicStateCreateInfo.create(frame,
609 0, dynamicStateEnables);
611 VkPipelineVertexInputStateCreateInfo vi = VkPipelineVertexInputStateCreateInfo.create(frame,
616 VkPipelineInputAssemblyStateCreateInfo ia = VkPipelineInputAssemblyStateCreateInfo.create(frame,
618 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
621 VkPipelineRasterizationStateCreateInfo rs = VkPipelineRasterizationStateCreateInfo.create(frame,
625 VK_POLYGON_MODE_FILL,
626 VK_CULL_MODE_BACK_BIT,
627 VK_FRONT_FACE_CLOCKWISE,
634 VkPipelineColorBlendAttachmentState att_state = VkPipelineColorBlendAttachmentState.create(frame,
636 VK_BLEND_FACTOR_ZERO,
637 VK_BLEND_FACTOR_ZERO,
639 VK_BLEND_FACTOR_ZERO,
640 VK_BLEND_FACTOR_ZERO,
644 VkPipelineColorBlendStateCreateInfo cb = VkPipelineColorBlendStateCreateInfo.create(frame,
649 1.0f, 1.0f, 1.0f, 1.0f);
651 VkPipelineViewportStateCreateInfo vp = VkPipelineViewportStateCreateInfo.create(frame,
656 VkPipelineDepthStencilStateCreateInfo ds = VkPipelineDepthStencilStateCreateInfo.create(frame,
660 VK_COMPARE_OP_LESS_OR_EQUAL,
665 VkStencilOpState back = ds.getBack();
667 back.setFailOp(VK_STENCIL_OP_KEEP);
668 back.setPassOp(VK_STENCIL_OP_KEEP);
669 back.setCompareOp(VK_COMPARE_OP_ALWAYS);
670 back.setCompareMask(0);
671 back.setReference(0);
672 back.setDepthFailOp(VK_STENCIL_OP_KEEP);
673 back.setWriteMask(0);
675 VkStencilOpState front = ds.getFront();
677 front.setFailOp(VK_STENCIL_OP_KEEP);
678 front.setPassOp(VK_STENCIL_OP_KEEP);
679 front.setCompareOp(VK_COMPARE_OP_ALWAYS);
680 front.setCompareMask(0);
681 front.setReference(0);
682 front.setDepthFailOp(VK_STENCIL_OP_KEEP);
683 front.setWriteMask(0);
685 VkPipelineMultisampleStateCreateInfo ms = VkPipelineMultisampleStateCreateInfo.create(frame,
688 0, //.sampleShadingEnable = VK_FALSE,
691 0, //.alphaToCoverageEnable = VK_FALSE,
692 0 //.alphaToOneEnable = VK_FALSE,
695 VkShaderModuleCreateInfo vsInfo = VkShaderModuleCreateInfo.create(frame,
699 VkShaderModuleCreateInfo fsInfo = VkShaderModuleCreateInfo.create(frame,
704 shader.setAtIndex(0, device.vkCreateShaderModule(vsInfo, scope));
705 shader.setAtIndex(1, device.vkCreateShaderModule(fsInfo, scope));
707 VkPipelineShaderStageCreateInfo shaderStages = VkPipelineShaderStageCreateInfo.createArray(2, (SegmentAllocator)scope);
709 // FIXME: createArray should initialise this
710 shaderStages.setSType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
711 shaderStages.setStage(VK_SHADER_STAGE_VERTEX_BIT);
712 shaderStages.setName("main", (SegmentAllocator)scope);
713 shaderStages.setModule(shader.get(0));
715 shaderStages.setSTypeAtIndex(1, VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
716 shaderStages.setStageAtIndex(1, VK_SHADER_STAGE_FRAGMENT_BIT);
717 shaderStages.setNameAtIndex(1, "main", (SegmentAllocator)scope);
718 shaderStages.setModuleAtIndex(1, shader.get(1));
720 VkGraphicsPipelineCreateInfo pipeline = VkGraphicsPipelineCreateInfo.create(frame,
739 res = device.vkCreateGraphicsPipelines(null, 1, pipeline, this.pipeline);
741 VkSemaphoreCreateInfo seminfo = VkSemaphoreCreateInfo.create(frame, 0);
742 chainSemaphore = device.vkCreateSemaphore(seminfo, scope);
744 VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.create(frame, 0);
745 drawFence = device.vkCreateFence(fenceInfo, scope);
749 void execute_begin_command_buffer() throws Exception {
750 /* DEPENDS on init_command() */
751 try ( Frame frame = Frame.frame()) {
752 VkCommandBufferBeginInfo cmd_buf_info = VkCommandBufferBeginInfo.create(frame,
756 cmd.getAtIndex(0).vkBeginCommandBuffer(cmd_buf_info);
760 void execute_end_command_buffer() throws Exception {
761 cmd.getAtIndex(0).vkEndCommandBuffer();
764 final static long FENCE_TIMEOUT = 100000000;
766 void execute_queue_command_buffer() throws Exception {
769 /* Queue the command buffer for execution */
770 /* FIXME: frame shoudl provide or take explicit scope */
771 try ( ResourceScope scope = ResourceScope.newConfinedScope(); Frame frame = Frame.frame()) {
772 IntArray pipe_stage_flags = IntArray.create(frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
773 VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.create(frame, 0);
774 HandleArray<VkFence> fences = VkFence.createArray(1, frame);
776 fences.setAtIndex(0, device.vkCreateFence(fenceInfo, scope));
778 VkSubmitInfo submit_info = VkSubmitInfo.create(frame,
779 1, null, pipe_stage_flags,
783 graphics_queue.vkQueueSubmit(1, submit_info, drawFence);
786 res = device.vkWaitForFences(1, fences, 1, FENCE_TIMEOUT);
787 } while (res == VK_TIMEOUT);
789 device.vkDestroyFence(fences.getAtIndex(0));
793 void cmd_viewport() {
794 try ( Frame frame = Frame.frame()) {
795 VkCommandBuffer cmd = this.cmd.getAtIndex(0);
796 VkViewport viewport = VkViewport.create(frame,
797 0, 0, width, height, 0.0f, 1.0f);
798 cmd.vkCmdSetViewport(0, 1, viewport);
802 void cmd_scissors() {
803 try ( Frame frame = Frame.frame()) {
804 VkCommandBuffer cmd = this.cmd.getAtIndex(0);
805 VkRect2D scissor = VkRect2D.create(frame);
806 VkExtent2D extent = scissor.getExtent();
808 extent.setWidth(width);
809 extent.setHeight(height);
811 cmd.vkCmdSetScissor(0, 1, scissor);
815 void cmd_paint() throws Exception {
817 try ( Frame frame = Frame.frame()) {
819 IntArray chainIndices = IntArray.createArray(1, frame);
820 VkCommandBuffer cmd = this.cmd.getAtIndex(0);
822 device.vkAcquireNextImageKHR(chain, ~0L, chainSemaphore, null, chainIndices);
823 chainIndex = chainIndices.getAtIndex(0);
824 LongArray offsets = LongArray.createArray(1, frame);
826 VkClearValue clear_values = VkClearValue.createArray(2, frame);
827 FloatArray col = clear_values.getColor().getFloat32();
828 col.setAtIndex(0, 0.2f);
829 col.setAtIndex(1, 0.2f);
830 col.setAtIndex(2, 0.2f);
831 col.setAtIndex(3, 0.2f);
832 VkClearDepthStencilValue depthStencil = clear_values.getAtIndex(1).getDepthStencil();
833 depthStencil.setDepth(1.0f);
834 depthStencil.setStencil(0);
836 System.out.printf("render framebuffer[%d] = %s\n", chainIndex, framebuffers.getAtIndex(chainIndex));
838 VkRenderPassBeginInfo rp_begin = VkRenderPassBeginInfo.create(frame,
840 framebuffers.getAtIndex(chainIndex),
842 VkExtent2D extent = rp_begin.getRenderArea().getExtent();
843 extent.setWidth(width);
844 extent.setHeight(height);
846 cmd.vkCmdBeginRenderPass(rp_begin, VK_SUBPASS_CONTENTS_INLINE);
848 cmd.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getAtIndex(0));
849 cmd.vkCmdBindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, NUM_DESCRIPTOR_SETS, desc_set, 0, null);
850 cmd.vkCmdBindVertexBuffers(0, 1, vertexBuffer, offsets);
855 cmd.vkCmdDraw(12 * 3, 1, 0, 0);
856 cmd.vkCmdEndRenderPass();
858 cmd.vkEndCommandBuffer();
860 IntArray pipe_stage_flags = IntArray.create(frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
861 HandleArray<VkSemaphore> semaphores = VkSemaphore.createArray(1, frame);//, chainSemaphore, scope);
863 semaphores.setAtIndex(0, chainSemaphore);
865 VkSubmitInfo submit_info = VkSubmitInfo.create(frame,
866 1, semaphores, pipe_stage_flags,
870 HandleArray<VkFence> fences = VkFence.createArray(1, frame);
872 fences.setAtIndex(0, drawFence);
874 // Queue the command buffer for execution
875 device.vkResetFences(1, fences);
877 graphics_queue.vkQueueSubmit(1, submit_info, drawFence);
879 // Make sure command buffer is finished before presenting
881 res = device.vkWaitForFences(1, fences, VK_TRUE, FENCE_TIMEOUT);
882 } while (res == VK_TIMEOUT);
884 // Now present the image in the window
885 HandleArray<VkSwapchainKHR> chains = VkSwapchainKHR.createArray(1, frame);
886 chains.setAtIndex(0, chain);
887 VkPresentInfoKHR present = VkPresentInfoKHR.create(frame,
894 present_queue.vkQueuePresentKHR(present);
899 * Buffers are created in three steps:
900 * 1) create buffer, specifying usage and size
901 * 2) allocate memory based on memory requirements
905 BufferMemory init_buffer(long dataSize, int usage, int properties, MemorySegment init) throws Exception {
906 try ( Frame frame = Frame.frame()) {
907 VkMemoryRequirements req = VkMemoryRequirements.create(frame);
908 VkBufferCreateInfo buf_info = VkBufferCreateInfo.create(frame,
912 VK_SHARING_MODE_EXCLUSIVE,
916 VkBuffer buffer = device.vkCreateBuffer(buf_info, scope);
918 device.vkGetBufferMemoryRequirements(buffer, req);
920 VkMemoryAllocateInfo alloc = VkMemoryAllocateInfo.create(frame,
922 find_memory_type(memory_properties, req.getMemoryTypeBits(), properties));
924 VkDeviceMemory memory = device.vkAllocateMemory(alloc, scope);
927 MemorySegment mem = device.vkMapMemory(memory, 0, dataSize, 0, scope);
929 device.vkUnmapMemory(memory);
932 device.vkBindBufferMemory(buffer, memory, 0);
934 return new BufferMemory(buffer, memory, dataSize);
939 device.vkDestroyFence(drawFence);
940 device.vkDestroySemaphore(chainSemaphore);
942 device.vkDestroyPipeline(pipeline.getAtIndex(0));
943 for (int i = 0; i < shader.size(); i++)
944 device.vkDestroyShaderModule(shader.getAtIndex(i));
947 uniform.free(device);
949 for (int i = 0; i < framebuffers.size(); i++)
950 device.vkDestroyFramebuffer(framebuffers.getAtIndex(i));
952 device.vkDestroyRenderPass(render_pass);
954 device.vkDestroyDescriptorPool(desc_pool);
955 device.vkDestroyPipelineLayout(pipeline_layout);
956 device.vkDestroyDescriptorSetLayout(desc_layout);
958 device.vkDestroyImageView(depthView);
959 device.vkFreeMemory(depthMemory);
960 device.vkDestroyImage(depthImage);
962 for (int i = 0; i < chainImageView.size(); i++)
963 device.vkDestroyImageView(chainImageView.getAtIndex(i));
965 device.vkDestroySwapchainKHR(chain);
967 device.vkDestroyCommandPool(cmd_pool);
968 device.vkDestroyDevice();
970 instance.vkDestroySurfaceKHR(surface);
975 instance.vkDestroyDebugUtilsMessengerEXT(logger);
976 instance.vkDestroyInstance();
980 * This finds the memory type index for the memory on a specific device.
982 static int find_memory_type(VkPhysicalDeviceMemoryProperties memory, int typeMask, int query) {
983 VkMemoryType mtypes = memory.getMemoryTypes();
985 for (int i = 0; i < memory.getMemoryTypeCount(); i++) {
986 if (((1 << i) & typeMask) != 0 && ((mtypes.getAtIndex(i).getPropertyFlags() & query) == query))
992 static int clampi(int v, int min, int max) {
993 return v < min ? min : v < max ? v : max;
996 void init_matrices() {
997 //float eye[] = new float[] {-5, 3, -10};
998 float eye[] = new float[]{0, 0, -10};
999 float centre[] = new float[]{0, 0, 0};
1000 float up[] = new float[]{0, -1, 0};
1001 float t0[] = new float[16], t1[] = new float[16];
1003 perspective(projection, (float)(Math.PI * 0.25), 1.0f, 0.1f, 100.0f);
1004 lookAt(view, eye, centre, up);
1006 mult4x4f(t0, clip, projection);
1007 mult4x4f(t1, t0, view);
1008 mult4x4f(mvp, t1, model);
1011 void demo() throws Exception {
1012 sdf_vs = ShaderIO.loadSdf_vs((SegmentAllocator)scope);
1013 sdf_fs = ShaderIO.loadSdf_fs((SegmentAllocator)scope);
1022 init_device_queue();
1030 init_vertexbuffer();
1033 execute_begin_command_buffer();
1037 System.out.println("Any key to quit");
1039 outer: while ((e = window.nextEvent(true)) != null) {
1050 public static void main(String[] args) throws Throwable {
1051 System.loadLibrary("vulkan");
1052 System.loadLibrary("X11");
1054 new TestSDF().demo();