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(
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,
146 logger = instance.vkCreateDebugUtilsMessengerEXT(info, scope);
149 //typedef VkBool32 (*PFN_vkDebugUtilsMessengerCallbackEXT)(VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *, void *);
152 void init_instance() throws Exception {
153 try ( Frame frame = Frame.frame()) {
154 VkInstanceCreateInfo info = VkInstanceCreateInfo.create(
156 VkApplicationInfo.create("cube", 1, "cube-engine", 2, VK_API_VERSION_1_0, frame),
157 new String[]{"VK_LAYER_KHRONOS_validation"},
158 new String[]{"VK_KHR_surface", "VK_KHR_xlib_surface", "VK_EXT_debug_utils"},
162 instance = VkInstance.vkCreateInstance(info, scope);
163 System.out.printf("instance = %s\n", instance);
169 VkSurfaceKHR surface;
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);
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;
186 devs = instance.vkEnumeratePhysicalDevices(frame, scope);
188 // Search for device and queue indices
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;
196 famprops = dev.vkGetPhysicalDeviceQueueFamilyProperties(frame);
198 for (int j = 0; j < famprops.length(); j++) {
201 dev.vkGetPhysicalDeviceSurfaceSupportKHR(j, surface, present$h);
202 present = present$h.get(0) != 0;
204 if (present && present_queue == -1)
206 if ((famprops.getQueueFlagsAtIndex(j) & VK_QUEUE_GRAPHICS_BIT) != 0) {
214 if (present_queue != -1 && graphics_queue != -1) {
221 throw new Exception("Cannot find a suitable device");
223 physicalDevice = devs.getAtIndex(devid);
224 present_queue_index = present_queue;
225 graphics_queue_index = graphics_queue;
228 memory_properties = VkPhysicalDeviceMemoryProperties.create((SegmentAllocator)scope);
229 physicalDevice.vkGetPhysicalDeviceMemoryProperties(memory_properties);
230 device_features = VkPhysicalDeviceFeatures.create((SegmentAllocator)scope);
231 physicalDevice.vkGetPhysicalDeviceFeatures(device_features);
233 FloatArray qpri = FloatArray.create(frame, 0.0f);
234 VkDeviceQueueCreateInfo qinfo = VkDeviceQueueCreateInfo.create(
239 String[] extensions = {
242 VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures.create(frame);
243 features.setDepthClamp(1);
244 VkDeviceCreateInfo devinfo = VkDeviceCreateInfo.create(
252 device = physicalDevice.vkCreateDevice(devinfo, scope);
254 System.out.printf("device = %s\n", device);
256 /* ************************************************************** */
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;
265 format = surfFormats.getFormatAtIndex(0);
268 VkSurfaceCapabilitiesKHR surfCapabilities = VkSurfaceCapabilitiesKHR.create(frame);
270 physicalDevice.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(surface, surfCapabilities);
271 IntArray presentModes = physicalDevice.vkGetPhysicalDeviceSurfacePresentModesKHR(surface, frame);
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()),
283 // If the surface size is defined, the swap chain size must match
284 swapchainExtent = surfCapabilities.getCurrentExtent();
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;
299 VkSwapchainCreateInfoKHR chaininfo = VkSwapchainCreateInfoKHR.create(
302 surfCapabilities.getMinImageCount(),
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.
311 (surfCapabilities.getSupportedTransforms() & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) != 0
312 ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : surfCapabilities.getCurrentTransform(),
314 VK_PRESENT_MODE_FIFO_KHR,
319 chain = device.vkCreateSwapchainKHR(chaininfo, scope);
323 chainImage = device.vkGetSwapchainImagesKHR(chain, (SegmentAllocator)scope);
324 chainImageCount = (int)chainImage.length();
325 chainImageView = VkImageView.createArray(chainImageCount, (SegmentAllocator)scope);
327 VkImageViewCreateInfo viewinfo = VkImageViewCreateInfo.create(
330 VK_IMAGE_VIEW_TYPE_2D,
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);
336 for (int i = 0; i < chainImageCount; i++) {
337 viewinfo.setImage(chainImage.get(i));
339 chainImageView.setAtIndex(i, device.vkCreateImageView(viewinfo, scope));
342 chainImageFormat = format;
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;
351 present_queue = device.vkGetDeviceQueue(present_queue_index, 0, scope);
355 void init_command() throws Exception {
356 try ( Frame frame = Frame.frame()) {
357 VkCommandPoolCreateInfo poolinfo = VkCommandPoolCreateInfo.create(
359 graphics_queue_index,
362 cmd_pool = device.vkCreateCommandPool(poolinfo, scope);
364 VkCommandBufferAllocateInfo cmdinfo = VkCommandBufferAllocateInfo.create(
366 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
370 cmd = device.vkAllocateCommandBuffers(cmdinfo, (SegmentAllocator)scope, scope);
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(
388 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
389 VK_SHARING_MODE_EXCLUSIVE,
391 VK_IMAGE_LAYOUT_UNDEFINED,
394 depthImage = device.vkCreateImage(imageinfo, scope);
396 device.vkGetImageMemoryRequirements(depthImage, req);
397 VkMemoryAllocateInfo alloc = VkMemoryAllocateInfo.create(
399 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(
409 VK_IMAGE_VIEW_TYPE_2D,
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);
423 depthView = device.vkCreateImageView(viewinfo, scope);
425 depthFormat = format;
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));
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(
438 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
440 VK_SHADER_STAGE_VERTEX_BIT,
443 VkDescriptorSetLayoutCreateInfo descriptor_layout = VkDescriptorSetLayoutCreateInfo.create(
448 desc_layout = device.vkCreateDescriptorSetLayout(descriptor_layout, scope);
449 layout_table.setAtIndex(0, desc_layout);
451 VkPipelineLayoutCreateInfo pipeline_info = VkPipelineLayoutCreateInfo.create(
458 pipeline_layout = device.vkCreatePipelineLayout(pipeline_info, scope);
460 VkDescriptorPoolSize type_count = VkDescriptorPoolSize.create(
461 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
465 VkDescriptorPoolCreateInfo descriptor_pool = VkDescriptorPoolCreateInfo.create(
471 desc_pool = device.vkCreateDescriptorPool(descriptor_pool, scope);
473 VkDescriptorSetAllocateInfo alloc_info = VkDescriptorSetAllocateInfo.create(
479 System.out.println(alloc_info);
481 desc_set = device.vkAllocateDescriptorSets(alloc_info, (SegmentAllocator)scope);
483 VkDescriptorBufferInfo uniformInfo = VkDescriptorBufferInfo.create(uniform.buffer, 0, uniform.size, frame);
484 VkWriteDescriptorSet writes = VkWriteDescriptorSet.create(
485 desc_set.getAtIndex(0),
489 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
495 device.vkUpdateDescriptorSets(1, writes, 0, null);
499 void init_render() throws Exception {
500 try ( Frame frame = Frame.frame()) {
501 VkAttachmentDescription attachments = VkAttachmentDescription.createArray(2, frame);
503 attachments.setFormat(chainImageFormat);
504 attachments.setSamples(NUM_SAMPLES);
505 attachments.setLoadOp(VK_ATTACHMENT_LOAD_OP_CLEAR);
506 attachments.setStoreOp(VK_ATTACHMENT_STORE_OP_STORE);
507 attachments.setStencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE);
508 attachments.setStencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE);
509 attachments.setInitialLayout(VK_IMAGE_LAYOUT_UNDEFINED);
510 attachments.setFinalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
511 attachments.setFlags(0);
513 attachments.setFormatAtIndex(1, depthFormat);
514 attachments.setSamplesAtIndex(1, NUM_SAMPLES);
515 attachments.setLoadOpAtIndex(1, VK_ATTACHMENT_LOAD_OP_CLEAR);
516 attachments.setStoreOpAtIndex(1, VK_ATTACHMENT_STORE_OP_STORE);
517 attachments.setStencilLoadOpAtIndex(1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
518 attachments.setStencilStoreOpAtIndex(1, VK_ATTACHMENT_STORE_OP_DONT_CARE);
519 attachments.setInitialLayoutAtIndex(1, VK_IMAGE_LAYOUT_UNDEFINED);
520 attachments.setFinalLayoutAtIndex(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
521 attachments.setFlagsAtIndex(1, 0);
523 VkAttachmentReference color_reference = VkAttachmentReference.create(
525 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
528 VkAttachmentReference depth_reference = VkAttachmentReference.create(
530 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
533 VkSubpassDescription subpass = VkSubpassDescription.create(
535 VK_PIPELINE_BIND_POINT_GRAPHICS,
544 VkRenderPassCreateInfo rp_info = VkRenderPassCreateInfo.create(
546 //(int)attachments.length(),
552 render_pass = device.vkCreateRenderPass(rp_info, scope);
556 void init_framebuffer() throws Exception {
557 try ( Frame frame = Frame.frame()) {
558 HandleArray<VkImageView> attachments = VkImageView.createArray(2, frame);
560 attachments.setAtIndex(1, depthView);
562 // FIXME: I don't think i want lenghts implied for types tbh
563 VkFramebufferCreateInfo fb_info = VkFramebufferCreateInfo.create(
573 framebuffers = VkFramebuffer.createArray(chainImage.length(), (SegmentAllocator)scope);
574 for (int i = 0; i < chainImage.size(); i++) {
575 attachments.setAtIndex(0, chainImageView.get(i));
576 framebuffers.setAtIndex(i, device.vkCreateFramebuffer(fb_info, scope));
577 System.out.printf("framebuffer[%d] = %s\n", i, framebuffers.getAtIndex(i));
582 void init_vertexbuffer() throws Exception {
583 try ( Frame frame = Frame.frame()) {
595 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));
597 vertexBuffer.setAtIndex(0, vertex.buffer);
599 /* ***************************************** */
600 vi_binding.setBinding(0);
601 vi_binding.setInputRate(VK_VERTEX_INPUT_RATE_VERTEX);
602 vi_binding.setStride(4 * 4);
604 vi_attribs.setBinding(0);
605 vi_attribs.setLocation(0);
606 vi_attribs.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT);
607 vi_attribs.setOffset(0);
608 //vi_attribs.setBindingAtIndex(1, 0);
609 //vi_attribs.setLocationAtIndex(1, 1);
610 //vi_attribs.setFormatAtIndex(1, VK_FORMAT_R32G32B32A32_SFLOAT);
611 //vi_attribs.setOffsetAtIndex(1, 16);
615 void init_pipeline() throws Exception {
617 try ( Frame frame = Frame.frame()) {
618 IntArray dynamicStateEnables = IntArray.create(frame,
619 VK_DYNAMIC_STATE_VIEWPORT,
620 VK_DYNAMIC_STATE_SCISSOR);
622 VkPipelineDynamicStateCreateInfo dynamicState = VkPipelineDynamicStateCreateInfo.create(
623 0, dynamicStateEnables,
626 VkPipelineVertexInputStateCreateInfo vi = VkPipelineVertexInputStateCreateInfo.create(
632 VkPipelineInputAssemblyStateCreateInfo ia = VkPipelineInputAssemblyStateCreateInfo.create(
634 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
638 VkPipelineRasterizationStateCreateInfo rs = VkPipelineRasterizationStateCreateInfo.create(
642 VK_POLYGON_MODE_FILL,
643 VK_CULL_MODE_BACK_BIT,
644 VK_FRONT_FACE_CLOCKWISE,
652 VkPipelineColorBlendAttachmentState att_state = VkPipelineColorBlendAttachmentState.create(
654 VK_BLEND_FACTOR_ZERO,
655 VK_BLEND_FACTOR_ZERO,
657 VK_BLEND_FACTOR_ZERO,
658 VK_BLEND_FACTOR_ZERO,
663 VkPipelineColorBlendStateCreateInfo cb = VkPipelineColorBlendStateCreateInfo.create(
668 1.0f, 1.0f, 1.0f, 1.0f,
671 VkPipelineViewportStateCreateInfo vp = VkPipelineViewportStateCreateInfo.create(
677 VkPipelineDepthStencilStateCreateInfo ds = VkPipelineDepthStencilStateCreateInfo.create(
681 VK_COMPARE_OP_LESS_OR_EQUAL,
687 VkStencilOpState back = ds.getBack();
689 back.setFailOp(VK_STENCIL_OP_KEEP);
690 back.setPassOp(VK_STENCIL_OP_KEEP);
691 back.setCompareOp(VK_COMPARE_OP_ALWAYS);
692 back.setCompareMask(0);
693 back.setReference(0);
694 back.setDepthFailOp(VK_STENCIL_OP_KEEP);
695 back.setWriteMask(0);
697 VkStencilOpState front = ds.getFront();
699 front.setFailOp(VK_STENCIL_OP_KEEP);
700 front.setPassOp(VK_STENCIL_OP_KEEP);
701 front.setCompareOp(VK_COMPARE_OP_ALWAYS);
702 front.setCompareMask(0);
703 front.setReference(0);
704 front.setDepthFailOp(VK_STENCIL_OP_KEEP);
705 front.setWriteMask(0);
707 VkPipelineMultisampleStateCreateInfo ms = VkPipelineMultisampleStateCreateInfo.create(
710 0, //.sampleShadingEnable = VK_FALSE,
713 0, //.alphaToCoverageEnable = VK_FALSE,
714 0, //.alphaToOneEnable = VK_FALSE,
718 VkShaderModuleCreateInfo vsInfo = VkShaderModuleCreateInfo.create(
723 VkShaderModuleCreateInfo fsInfo = VkShaderModuleCreateInfo.create(
729 shader.setAtIndex(0, device.vkCreateShaderModule(vsInfo, scope));
730 shader.setAtIndex(1, device.vkCreateShaderModule(fsInfo, scope));
732 VkPipelineShaderStageCreateInfo shaderStages = VkPipelineShaderStageCreateInfo.createArray(2, (SegmentAllocator)scope);
734 shaderStages.setStage(VK_SHADER_STAGE_VERTEX_BIT);
735 shaderStages.setName("main", (SegmentAllocator)scope);
736 shaderStages.setModule(shader.get(0));
738 shaderStages.setStageAtIndex(1, VK_SHADER_STAGE_FRAGMENT_BIT);
739 shaderStages.setNameAtIndex(1, "main", (SegmentAllocator)scope);
740 shaderStages.setModuleAtIndex(1, shader.get(1));
742 VkGraphicsPipelineCreateInfo pipeline = VkGraphicsPipelineCreateInfo.create(
762 res = device.vkCreateGraphicsPipelines(null, 1, pipeline, this.pipeline);
764 VkSemaphoreCreateInfo seminfo = VkSemaphoreCreateInfo.create(0, frame);
765 chainSemaphore = device.vkCreateSemaphore(seminfo, scope);
767 VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.create(0, frame);
768 drawFence = device.vkCreateFence(fenceInfo, scope);
772 void execute_begin_command_buffer() throws Exception {
773 /* DEPENDS on init_command() */
774 try ( Frame frame = Frame.frame()) {
775 VkCommandBufferBeginInfo cmd_buf_info = VkCommandBufferBeginInfo.create(
780 cmd.getAtIndex(0).vkBeginCommandBuffer(cmd_buf_info);
784 void execute_end_command_buffer() throws Exception {
785 cmd.getAtIndex(0).vkEndCommandBuffer();
788 final static long FENCE_TIMEOUT = 100000000;
790 void execute_queue_command_buffer() throws Exception {
793 /* Queue the command buffer for execution */
794 /* FIXME: frame shoudl provide or take explicit scope */
795 try ( ResourceScope scope = ResourceScope.newConfinedScope(); Frame frame = Frame.frame()) {
796 IntArray pipe_stage_flags = IntArray.create(frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
797 VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.create(0, frame);
798 HandleArray<VkFence> fences = VkFence.createArray(1, frame);
800 fences.setAtIndex(0, device.vkCreateFence(fenceInfo, scope));
802 VkSubmitInfo submit_info = VkSubmitInfo.create(
803 1, null, pipe_stage_flags,
808 graphics_queue.vkQueueSubmit(1, submit_info, drawFence);
811 res = device.vkWaitForFences(1, fences, 1, FENCE_TIMEOUT);
812 } while (res == VK_TIMEOUT);
814 device.vkDestroyFence(fences.getAtIndex(0));
818 void cmd_viewport() {
819 try ( Frame frame = Frame.frame()) {
820 VkCommandBuffer cmd = this.cmd.getAtIndex(0);
821 VkViewport viewport = VkViewport.create(
822 0, 0, width, height, 0.0f, 1.0f,
824 cmd.vkCmdSetViewport(0, 1, viewport);
828 void cmd_scissors() {
829 try ( Frame frame = Frame.frame()) {
830 VkCommandBuffer cmd = this.cmd.getAtIndex(0);
831 VkRect2D scissor = VkRect2D.create(frame);
832 VkExtent2D extent = scissor.getExtent();
834 extent.setWidth(width);
835 extent.setHeight(height);
837 cmd.vkCmdSetScissor(0, 1, scissor);
841 void cmd_paint() throws Exception {
843 try ( Frame frame = Frame.frame()) {
845 IntArray chainIndices = IntArray.createArray(1, frame);
846 VkCommandBuffer cmd = this.cmd.getAtIndex(0);
848 device.vkAcquireNextImageKHR(chain, ~0L, chainSemaphore, null, chainIndices);
849 chainIndex = chainIndices.getAtIndex(0);
850 LongArray offsets = LongArray.createArray(1, frame);
852 VkClearValue clear_values = VkClearValue.createArray(2, frame);
853 clear_values.getColor().setFloat32(0.2f, 0.2f, 0.2f, 0.2f);
854 VkClearDepthStencilValue depthStencil = clear_values.getAtIndex(1).getDepthStencil();
855 depthStencil.setDepth(1.0f);
856 depthStencil.setStencil(0);
858 System.out.printf("render framebuffer[%d] = %s\n", chainIndex, framebuffers.getAtIndex(chainIndex));
860 VkRenderPassBeginInfo rp_begin = VkRenderPassBeginInfo.create(
862 framebuffers.getAtIndex(chainIndex),
867 cmd.vkCmdBeginRenderPass(rp_begin, VK_SUBPASS_CONTENTS_INLINE);
869 cmd.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getAtIndex(0));
870 cmd.vkCmdBindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, NUM_DESCRIPTOR_SETS, desc_set, 0, null);
871 cmd.vkCmdBindVertexBuffers(0, 1, vertexBuffer, offsets);
876 cmd.vkCmdDraw(12 * 3, 1, 0, 0);
877 cmd.vkCmdEndRenderPass();
879 cmd.vkEndCommandBuffer();
881 IntArray pipe_stage_flags = IntArray.create(frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
882 HandleArray<VkSemaphore> semaphores = VkSemaphore.createArray(1, frame);//, chainSemaphore, scope);
884 semaphores.setAtIndex(0, chainSemaphore);
886 VkSubmitInfo submit_info = VkSubmitInfo.create(
887 1, semaphores, pipe_stage_flags,
892 HandleArray<VkFence> fences = VkFence.createArray(1, frame);
894 fences.setAtIndex(0, drawFence);
896 // Queue the command buffer for execution
897 device.vkResetFences(1, fences);
899 graphics_queue.vkQueueSubmit(1, submit_info, drawFence);
901 // Make sure command buffer is finished before presenting
903 res = device.vkWaitForFences(1, fences, VK_TRUE, FENCE_TIMEOUT);
904 } while (res == VK_TIMEOUT);
906 // Now present the image in the window
907 HandleArray<VkSwapchainKHR> chains = VkSwapchainKHR.createArray(1, frame);
908 chains.setAtIndex(0, chain);
909 VkPresentInfoKHR present = VkPresentInfoKHR.create(
917 present_queue.vkQueuePresentKHR(present);
922 * Buffers are created in three steps:
923 * 1) create buffer, specifying usage and size
924 * 2) allocate memory based on memory requirements
928 BufferMemory init_buffer(long dataSize, int usage, int properties, MemorySegment init) throws Exception {
929 try ( Frame frame = Frame.frame()) {
930 VkMemoryRequirements req = VkMemoryRequirements.create(frame);
931 VkBufferCreateInfo buf_info = VkBufferCreateInfo.create(
935 VK_SHARING_MODE_EXCLUSIVE,
940 VkBuffer buffer = device.vkCreateBuffer(buf_info, scope);
942 device.vkGetBufferMemoryRequirements(buffer, req);
944 VkMemoryAllocateInfo alloc = VkMemoryAllocateInfo.create(
946 find_memory_type(memory_properties, req.getMemoryTypeBits(), properties),
949 VkDeviceMemory memory = device.vkAllocateMemory(alloc, scope);
952 MemorySegment mem = device.vkMapMemory(memory, 0, dataSize, 0, scope);
954 device.vkUnmapMemory(memory);
957 device.vkBindBufferMemory(buffer, memory, 0);
959 return new BufferMemory(buffer, memory, dataSize);
964 device.vkDestroyFence(drawFence);
965 device.vkDestroySemaphore(chainSemaphore);
967 device.vkDestroyPipeline(pipeline.getAtIndex(0));
968 for (int i = 0; i < shader.size(); i++)
969 device.vkDestroyShaderModule(shader.getAtIndex(i));
972 uniform.free(device);
974 for (int i = 0; i < framebuffers.size(); i++)
975 device.vkDestroyFramebuffer(framebuffers.getAtIndex(i));
977 device.vkDestroyRenderPass(render_pass);
979 device.vkDestroyDescriptorPool(desc_pool);
980 device.vkDestroyPipelineLayout(pipeline_layout);
981 device.vkDestroyDescriptorSetLayout(desc_layout);
983 device.vkDestroyImageView(depthView);
984 device.vkFreeMemory(depthMemory);
985 device.vkDestroyImage(depthImage);
987 for (int i = 0; i < chainImageView.size(); i++)
988 device.vkDestroyImageView(chainImageView.getAtIndex(i));
990 device.vkDestroySwapchainKHR(chain);
992 device.vkDestroyCommandPool(cmd_pool);
993 device.vkDestroyDevice();
995 instance.vkDestroySurfaceKHR(surface);
1000 instance.vkDestroyDebugUtilsMessengerEXT(logger);
1001 instance.vkDestroyInstance();
1005 * This finds the memory type index for the memory on a specific device.
1007 static int find_memory_type(VkPhysicalDeviceMemoryProperties memory, int typeMask, int query) {
1008 VkMemoryType mtypes = memory.getMemoryTypes();
1010 for (int i = 0; i < memory.getMemoryTypeCount(); i++) {
1011 if (((1 << i) & typeMask) != 0 && ((mtypes.getAtIndex(i).getPropertyFlags() & query) == query))
1017 static int clampi(int v, int min, int max) {
1018 return v < min ? min : v < max ? v : max;
1021 void init_matrices() {
1022 //float eye[] = new float[] {-5, 3, -10};
1023 float eye[] = new float[]{0, 0, -10};
1024 float centre[] = new float[]{0, 0, 0};
1025 float up[] = new float[]{0, -1, 0};
1026 float t0[] = new float[16], t1[] = new float[16];
1028 perspective(projection, (float)(Math.PI * 0.25), 1.0f, 0.1f, 100.0f);
1029 lookAt(view, eye, centre, up);
1031 mult4x4f(t0, clip, projection);
1032 mult4x4f(t1, t0, view);
1033 mult4x4f(mvp, t1, model);
1036 void demo() throws Exception {
1037 sdf_vs = ShaderIO.loadSdf_vs((SegmentAllocator)scope);
1038 sdf_fs = ShaderIO.loadSdf_fs((SegmentAllocator)scope);
1047 init_device_queue();
1055 init_vertexbuffer();
1058 execute_begin_command_buffer();
1062 System.out.println("Any key to quit");
1064 outer: while ((e = window.nextEvent(true)) != null) {
1075 public static void main(String[] args) throws Throwable {
1076 System.loadLibrary("vulkan");
1077 System.loadLibrary("X11");
1079 new TestSDF().demo();