Added indexed accessors for embedded arrays.
Added initialisers for embedded arrays.
Tweaked some of the implied call lengths.
notzed.clstatic_JMAIN = opencl.test.clinfo
notzed.vkregistry.test_JMAIN = vulkan.test.TestMandelbrot vulkan.test.TestCube
notzed.vkheader.test_JMAIN = vulkan.test.TestMandelbrot vulkan.test.TestCube
-notzed.vulkan.test_JMAIN = vulkan.test.TestMandelbrot
+notzed.vulkan.test_JMAIN = vulkan.test.TestMandelbrot vulkan.test.TestCube
$(foreach module,$(java_MODULES),$(eval $(module)_JMAINFLAGS=--enable-native-access=notzed.nativez,$(module)))
--- /dev/null
+
+package vulkan.test;
+
+//struct Vertex {
+// float posX, posY, posZ, posW; // Position data
+// float r, g, b, a; // Color
+//};
+
+class Cube {
+ static final int dataStride = 8 * 4;
+ static final float[] data = new float[] {
+ // red face
+ -1, -1, 1, 1.f, 1.f, 0.f, 0.f, 1.f,
+ -1, 1, 1, 1.f, 1.f, 0.f, 0.f, 1.f,
+ 1, -1, 1, 1.f, 1.f, 0.f, 0.f, 1.f,
+ 1, -1, 1, 1.f, 1.f, 0.f, 0.f, 1.f,
+ -1, 1, 1, 1.f, 1.f, 0.f, 0.f, 1.f,
+ 1, 1, 1, 1.f, 1.f, 0.f, 0.f, 1.f,
+ // green face
+ -1, -1, -1, 1.f, 0.f, 1.f, 0.f, 1.f,
+ 1, -1, -1, 1.f, 0.f, 1.f, 0.f, 1.f,
+ -1, 1, -1, 1.f, 0.f, 1.f, 0.f, 1.f,
+ -1, 1, -1, 1.f, 0.f, 1.f, 0.f, 1.f,
+ 1, -1, -1, 1.f, 0.f, 1.f, 0.f, 1.f,
+ 1, 1, -1, 1.f, 0.f, 1.f, 0.f, 1.f,
+ // blue face
+ -1, 1, 1, 1.f, 0.f, 0.f, 1.f, 1.f,
+ -1, -1, 1, 1.f, 0.f, 0.f, 1.f, 1.f,
+ -1, 1, -1, 1.f, 0.f, 0.f, 1.f, 1.f,
+ -1, 1, -1, 1.f, 0.f, 0.f, 1.f, 1.f,
+ -1, -1, 1, 1.f, 0.f, 0.f, 1.f, 1.f,
+ -1, -1, -1, 1.f, 0.f, 0.f, 1.f, 1.f,
+ // yellow face
+ 1, 1, 1, 1.f, 1.f, 1.f, 0.f, 1.f,
+ 1, 1, -1, 1.f, 1.f, 1.f, 0.f, 1.f,
+ 1, -1, 1, 1.f, 1.f, 1.f, 0.f, 1.f,
+ 1, -1, 1, 1.f, 1.f, 1.f, 0.f, 1.f,
+ 1, 1, -1, 1.f, 1.f, 1.f, 0.f, 1.f,
+ 1, -1, -1, 1.f, 1.f, 1.f, 0.f, 1.f,
+ // magenta face
+ 1, 1, 1, 1.f, 1.f, 0.f, 1.f, 1.f,
+ -1, 1, 1, 1.f, 1.f, 0.f, 1.f, 1.f,
+ 1, 1, -1, 1.f, 1.f, 0.f, 1.f, 1.f,
+ 1, 1, -1, 1.f, 1.f, 0.f, 1.f, 1.f,
+ -1, 1, 1, 1.f, 1.f, 0.f, 1.f, 1.f,
+ -1, 1, -1, 1.f, 1.f, 0.f, 1.f, 1.f,
+ // cyan face
+ 1, -1, 1, 1.f, 0.f, 1.f, 1.f, 1.f,
+ 1, -1, -1, 1.f, 0.f, 1.f, 1.f, 1.f,
+ -1, -1, 1, 1.f, 0.f, 1.f, 1.f, 1.f,
+ -1, -1, 1, 1.f, 0.f, 1.f, 1.f, 1.f,
+ 1, -1, -1, 1.f, 0.f, 1.f, 1.f, 1.f,
+ -1, -1, -1, 1.f, 0.f, 1.f, 1.f, 1.f,
+ };
+}
--- /dev/null
+
+package vulkan.test;
+
+import static java.lang.Math.*;
+import java.util.Arrays;
+
+public class GLMaths {
+ public static void identity4f(float []matrix) {
+ Arrays.fill(matrix, 0.0f);
+ for (int i = 0; i < 4; i++)
+ matrix[i * 4 + i] = 1.0f;
+ }
+
+ public static float length3f(float [] a) {
+ float sum = 0;
+ for (int i = 0; i < 3; i++)
+ sum += a[i] * a[i];
+ return (float)sqrt(sum);
+ }
+
+ public static void sub3f(float [] c, float [] a, float [] b) {
+ for (int i = 0; i < 3; i++)
+ c[i] = a[i] - b[i];
+ }
+
+ public static void norm3f(float [] vec) {
+ float fix = 1.0f / length3f(vec);
+ for (int i = 0; i < 3; i++)
+ vec[i] *= fix;
+ }
+
+ public static void cross3f(float [] c, float [] a, float [] b) {
+ c[0] = a[1] * b[2] - a[2] * b[1];
+ c[1] = a[2] * b[0] - a[0] * b[2];
+ c[2] = a[0] * b[1] - a[1] * b[0];
+ }
+
+ public static float dot3f(float [] a, float [] b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ }
+
+ public static float [] mult4x4f(float [] c, float [] b, float [] a) {
+ c[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12];
+ c[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13];
+ c[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14];
+ c[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15];
+
+ c[4] = a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12];
+ c[5] = a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13];
+ c[6] = a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14];
+ c[7] = a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15];
+
+ c[8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12];
+ c[9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13];
+ c[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14];
+ c[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15];
+
+ c[12] = a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12];
+ c[13] = a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13];
+ c[14] = a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14];
+ c[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15];
+
+ return c;
+ }
+
+ public static void lookAt(float []mat, float []eye, float []centre, float []up) {
+ float forward[] = new float[3], side[] = new float[3], u[] = new float[3];
+
+ sub3f(forward, centre, eye);
+ norm3f(forward);
+ cross3f(side, forward, up);
+ norm3f(side);
+ cross3f(u, side, forward);
+
+ mat[0] = side[0];
+ mat[4] = side[1];
+ mat[8] = side[2];
+
+ mat[1] = u[0];
+ mat[5] = u[1];
+ mat[9] = u[2];
+
+ mat[2] = -forward[0];
+ mat[6] = -forward[1];
+ mat[10] = -forward[2];
+
+ mat[12] = -dot3f(side, eye);
+ mat[13] = -dot3f(u, eye);
+ mat[14] = dot3f(forward, eye);
+
+ mat[3] = 0.0f;
+ mat[7] = 0.0f;
+ mat[11] = 0.0f;
+
+ mat[15] = 1.0f;
+ }
+
+ public static void frustum(float []mat, float left, float right, float bottom, float top, float znear, float zfar) {
+ float temp, temp2, temp3, temp4;
+
+ temp = 2.0f * znear;
+ temp2 = right - left;
+ temp3 = top - bottom;
+ temp4 = zfar - znear;
+ mat[0] = temp / temp2;
+ mat[1] = 0.0f;
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+ mat[4] = 0.0f;
+ mat[5] = temp / temp3;
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+ mat[8] = (right + left) / temp2;
+ mat[9] = (top + bottom) / temp3;
+ mat[10] = (-zfar - znear) / temp4;
+ mat[11] = -1.0f;
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = (-temp * zfar) / temp4;
+ mat[15] = 0.0f;
+ }
+
+ public static void perspective(float []mat, float fovy, float aspect, float znear, float zfar) {
+ float ymax, xmax;
+
+ ymax = znear * (float)tan(fovy * 0.5f);
+ xmax = ymax * aspect;
+
+ frustum(mat, -xmax, xmax, -ymax, ymax, znear, zfar);
+ }
+}
--- /dev/null
+ /*
+The MIT License (MIT)
+
+Copyright (C) 2017 Eric Arnebäck
+Copyright (C) 2019 Michael Zucchi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+ */
+
+/*
+ * This is a Java conversion of a C conversion of this:
+ * https://github.com/Erkaman/vulkan_minimal_compute
+ *
+ * It's been simplified a bit and converted to the 'zvk' api.
+ */
+
+package vulkan.test;
+
+import java.io.InputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.Channels;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.image.MemoryImageSource;
+import javax.swing.AbstractAction;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.KeyStroke;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+import java.util.Collections;
+
+import java.lang.invoke.*;
+import jdk.incubator.foreign.*;
+import jdk.incubator.foreign.MemoryLayout.PathElement;
+import au.notzed.nativez.*;
+
+import vulkan.*;
+import static vulkan.VkConstants.*;
+
+import xlib.*;
+import static xlib.XLib.*;
+import static vulkan.test.GLMaths.*;
+
+public class TestCube {
+ static final boolean debug = true;
+
+ final static int NUM_SAMPLES = VK_SAMPLE_COUNT_1_BIT;
+ final static int NUM_DESCRIPTOR_SETS = 1;
+
+ ResourceScope scope = ResourceScope.newSharedScope();
+
+ int width = 800;
+ int height = 800;
+ float projection[] = new float[16];
+ float view[] = new float[16];
+ float model[] = new float[16];
+ float clip[] = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 1.0f
+ };
+ float mvp[] = new float[16];
+
+ VkInstance instance;
+ VkPhysicalDevice physicalDevice;
+ VkPhysicalDeviceMemoryProperties memory_properties;
+ VkPhysicalDeviceFeatures device_features;
+
+ int present_queue_index;
+ int graphics_queue_index;
+
+ VkDevice device;
+ VkSwapchainKHR chain;
+
+ VkQueue graphics_queue;
+ VkQueue present_queue;
+
+ int chainImageFormat;
+ HandleArray<VkImage> chainImage;
+ HandleArray<VkImageView> chainImageView;
+
+ int depthFormat;
+ VkImage depthImage;
+ VkImageView depthView;
+ VkDeviceMemory depthMemory;
+
+ VkCommandPool cmd_pool;
+ HandleArray<VkCommandBuffer> cmd;
+
+ BufferMemory uniform;
+ VkPipelineLayout pipeline_layout;
+
+ VkDescriptorSetLayout desc_layout;
+ VkDescriptorPool desc_pool;
+ HandleArray<VkDescriptorSet> desc_set;
+
+
+ VkRenderPass render_pass;
+ HandleArray<VkFramebuffer> framebuffers;
+
+ BufferMemory vertex;
+ HandleArray<VkBuffer> vertexBuffer = VkBuffer.createArray(1, (SegmentAllocator)scope);
+ VkVertexInputBindingDescription vi_binding = VkVertexInputBindingDescription.createArray(1, (SegmentAllocator)scope);
+ VkVertexInputAttributeDescription vi_attribs = VkVertexInputAttributeDescription.createArray(2, (SegmentAllocator)scope);
+
+ IntArray cube_vs;
+ IntArray cube_fs;
+ HandleArray<VkShaderModule> shader = VkShaderModule.createArray(2, (SegmentAllocator)scope);
+
+ HandleArray<VkPipeline> pipeline = VkPipeline.createArray(1, (SegmentAllocator)scope);
+
+ VkSemaphore chainSemaphore;
+ VkFence drawFence;
+
+ record BufferMemory (VkBuffer buffer, VkDeviceMemory memory, long size) {
+ public void free(VkDevice device) {
+ device.vkFreeMemory(memory);
+ device.vkDestroyBuffer(buffer);
+ }
+ }
+
+ VkDebugUtilsMessengerEXT logger;
+
+ void init_debug() throws Exception {
+ if (!debug)
+ return;
+ try (Frame frame = Frame.frame()) {
+ var cb = PFN_vkDebugUtilsMessengerCallbackEXT.upcall((severity, flags, data) -> {
+ System.out.printf("Debug: %d: %s\n", severity, data.getMessage());
+ return 0;
+ }, scope);
+ VkDebugUtilsMessengerCreateInfoEXT info = VkDebugUtilsMessengerCreateInfoEXT.create(frame,
+ 0,
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
+ cb,
+ null);
+
+ logger = instance.vkCreateDebugUtilsMessengerEXT(info, scope);
+ }
+
+ //typedef VkBool32 (*PFN_vkDebugUtilsMessengerCallbackEXT)(VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *, void *);
+
+ }
+
+ void init_instance() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ VkInstanceCreateInfo info = VkInstanceCreateInfo.create(frame,
+ 0,
+ VkApplicationInfo.create(frame, "cube", 1, "cube-engine", 2, VK_MAKE_API_VERSION(0, 1, 0, 0)),
+ new String[] { "VK_LAYER_KHRONOS_validation" },
+ new String[] { "VK_KHR_surface", "VK_KHR_xlib_surface", "VK_EXT_debug_utils" }
+ );
+
+ instance = VkInstance.vkCreateInstance(info, scope);
+ System.out.printf("instance = %s\n", instance);
+ }
+ }
+
+ XDisplay display;
+ long window;
+ long wm_delete_window;
+ VkSurfaceKHR surface;
+
+ void init_surface() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ XInitThreads();
+ display = XOpenDisplay(null);
+ long visualMask = VisualScreenMask;
+ IntArray numberOfVisuals = IntArray.createArray(1, frame);
+ XVisualInfo vInfoTemplate = XVisualInfo.create(frame);
+
+ vInfoTemplate.setScreen(DefaultScreen(display));
+
+ XVisualInfo visualInfo = XGetVisualInfo(display, visualMask, vInfoTemplate, numberOfVisuals);
+ long colormap = XCreateColormap(display, RootWindow(display, vInfoTemplate.getScreen()), visualInfo.getVisual(), AllocNone);
+
+ XSetWindowAttributes windowAttributes = XSetWindowAttributes.create(frame);
+
+ windowAttributes.setColormap(colormap);
+ windowAttributes.setBackgroundPixel(0xffffffff);
+ windowAttributes.setBorderPixel(0);
+ windowAttributes.setEventMask(KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask);
+
+ window = XCreateWindow(display, RootWindow(display, vInfoTemplate.getScreen()),
+ 0, 0, width, height,
+ 0, visualInfo.getDepth(), InputOutput, visualInfo.getVisual(),
+ CWBackPixel | CWBorderPixel | CWEventMask | CWColormap, windowAttributes);
+
+ XSelectInput(display, window, ExposureMask | KeyPressMask);
+ XMapWindow(display, window);
+ XFlush(display);
+ wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0);
+
+ VkXlibSurfaceCreateInfoKHR surfaceinfo = VkXlibSurfaceCreateInfoKHR.create(frame,
+ 0,
+ display,
+ window);
+
+ surface = instance.vkCreateXlibSurfaceKHR(surfaceinfo, scope);
+ System.out.printf("surface: %s\n", surface);
+ }
+ }
+
+ void init_device() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ IntArray count$h = IntArray.create(frame, 1);
+ IntArray present$h = IntArray.create(frame, 1);
+ HandleArray<VkPhysicalDevice> devs;
+ int count;
+ int res;
+
+ devs = instance.vkEnumeratePhysicalDevices(frame, scope);
+
+ // Search for device and queue indices
+ int devid = -1;
+ int present_queue = -1;
+ int graphics_queue = -1;
+ for (int i = 0; i < devs.length(); i++) {
+ VkPhysicalDevice dev = devs.getAtIndex(i);
+ VkQueueFamilyProperties famprops;
+
+ famprops = dev.vkGetPhysicalDeviceQueueFamilyProperties(frame);
+
+ for (int j = 0; j < famprops.length(); j++) {
+ boolean present;
+
+ dev.vkGetPhysicalDeviceSurfaceSupportKHR(j, surface, present$h);
+ present = present$h.get(0) != 0;
+
+ if (present && present_queue == -1)
+ present_queue = j;
+ if ((famprops.getQueueFlagsAtIndex(j) & VK_QUEUE_GRAPHICS_BIT) != 0) {
+ graphics_queue = j;
+ if (present) {
+ present_queue = j;
+ break;
+ }
+ }
+ }
+ if (present_queue != -1 && graphics_queue != -1) {
+ devid = i;
+ break;
+ }
+ }
+
+ if (devid == -1)
+ throw new Exception("Cannot find a suitable device");
+
+ physicalDevice = devs.getAtIndex(devid);
+ present_queue_index = present_queue;
+ graphics_queue_index = graphics_queue;
+
+ // NOTE: app scope
+ memory_properties = VkPhysicalDeviceMemoryProperties.create((SegmentAllocator)scope);
+ physicalDevice.vkGetPhysicalDeviceMemoryProperties(memory_properties);
+ device_features = VkPhysicalDeviceFeatures.create((SegmentAllocator)scope);
+ physicalDevice.vkGetPhysicalDeviceFeatures(device_features);
+
+ FloatArray qpri = FloatArray.create(frame, 0.0f);
+ VkDeviceQueueCreateInfo qinfo = VkDeviceQueueCreateInfo.create(
+ frame,
+ 0,
+ graphics_queue,
+ qpri);
+ String [] extensions = {
+ "VK_KHR_swapchain"
+ };
+ VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures.create(frame);
+ features.setDepthClamp(1);
+ VkDeviceCreateInfo devinfo = VkDeviceCreateInfo.create(
+ frame,
+ 0,
+ qinfo,
+ null,
+ extensions,
+ features);
+
+ device = physicalDevice.vkCreateDevice(devinfo, scope);
+
+ System.out.printf("device = %s\n", device);
+
+ /* ************************************************************** */
+ int format;
+ VkSurfaceFormatKHR surfFormats = physicalDevice.vkGetPhysicalDeviceSurfaceFormatsKHR(surface, frame);
+ // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
+ // the surface has no preferred format. Otherwise, at least one
+ // supported format will be returned.
+ if (surfFormats.length() == 1 && surfFormats.getFormatAtIndex(0) == VK_FORMAT_UNDEFINED) {
+ format = VK_FORMAT_B8G8R8A8_UNORM;
+ } else {
+ format = surfFormats.getFormatAtIndex(0);
+ }
+
+ VkSurfaceCapabilitiesKHR surfCapabilities = VkSurfaceCapabilitiesKHR.create(frame);
+
+ physicalDevice.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(surface, surfCapabilities);
+ IntArray presentModes = physicalDevice.vkGetPhysicalDeviceSurfacePresentModesKHR(surface, frame);
+
+ VkExtent2D swapchainExtent;
+ // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
+ if (surfCapabilities.getCurrentExtent().getWidth() == 0xFFFFFFFF) {
+ // If the surface size is undefined, the size is set to
+ // the size of the images requested.
+ swapchainExtent = VkExtent2D.create(frame,
+ clampi(width, surfCapabilities.getMinImageExtent().getWidth(), surfCapabilities.getMaxImageExtent().getWidth()),
+ clampi(height, surfCapabilities.getMinImageExtent().getHeight(), surfCapabilities.getMaxImageExtent().getHeight()));
+ } else {
+ // If the surface size is defined, the swap chain size must match
+ swapchainExtent = surfCapabilities.getCurrentExtent();
+ }
+ int compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ int compositeAlphaFlags[] = {
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
+ VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
+ };
+ for (int flag: compositeAlphaFlags) {
+ if ((surfCapabilities.getSupportedCompositeAlpha() & flag) != 0) {
+ compositeAlpha = flag;
+ break;
+ }
+ }
+
+ VkSwapchainCreateInfoKHR chaininfo = VkSwapchainCreateInfoKHR.create(frame,
+ 0,
+ surface,
+ surfCapabilities.getMinImageCount(),
+ format,
+ VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ 1, //.imageArrayLayers = 1,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ VK_SHARING_MODE_EXCLUSIVE,
+ // assumes queues are same.
+ null,
+ (surfCapabilities.getSupportedTransforms() & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) != 0
+ ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : surfCapabilities.getCurrentTransform(),
+ compositeAlpha,
+ VK_PRESENT_MODE_FIFO_KHR,
+ VK_TRUE,
+ null);
+ chaininfo.getImageExtent().setWidth(swapchainExtent.getWidth());
+ chaininfo.getImageExtent().setHeight(swapchainExtent.getHeight());
+
+ chain = device.vkCreateSwapchainKHR(chaininfo, scope);
+
+ int chainImageCount;
+
+ chainImage = device.vkGetSwapchainImagesKHR(chain, (SegmentAllocator)scope);
+ chainImageCount = (int)chainImage.length();
+ chainImageView = VkImageView.createArray(chainImageCount, (SegmentAllocator)scope);
+
+ VkImageViewCreateInfo viewinfo = VkImageViewCreateInfo.create(frame,
+ 0,
+ null,
+ VK_IMAGE_VIEW_TYPE_2D,
+ format);
+ VkComponentMapping components = viewinfo.getComponents();
+ components.setR(VK_COMPONENT_SWIZZLE_R);
+ components.setG(VK_COMPONENT_SWIZZLE_G);
+ components.setB(VK_COMPONENT_SWIZZLE_B);
+ components.setA(VK_COMPONENT_SWIZZLE_A);
+ VkImageSubresourceRange subresourceRange = viewinfo.getSubresourceRange();
+ subresourceRange.setAspectMask(VK_IMAGE_ASPECT_COLOR_BIT);
+ subresourceRange.setLevelCount(1);
+ subresourceRange.setLayerCount(1);
+
+ for (int i = 0; i < chainImageCount; i++) {
+ viewinfo.setImage(chainImage.get(i));
+
+ chainImageView.setAtIndex(i, device.vkCreateImageView(viewinfo, scope));
+ }
+
+ chainImageFormat = format;
+ }
+ }
+
+ void init_device_queue() {
+ graphics_queue = device.vkGetDeviceQueue(graphics_queue_index, 0, scope);
+ if (graphics_queue_index == present_queue_index) {
+ present_queue = graphics_queue;
+ } else {
+ present_queue = device.vkGetDeviceQueue(present_queue_index, 0, scope);
+ }
+ }
+
+ void init_command() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ VkCommandPoolCreateInfo poolinfo = VkCommandPoolCreateInfo.create(frame,
+ 0,
+ graphics_queue_index);
+
+ cmd_pool = device.vkCreateCommandPool(poolinfo, scope);
+
+ VkCommandBufferAllocateInfo cmdinfo = VkCommandBufferAllocateInfo.create(frame,
+ cmd_pool,
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ 1);
+
+ cmd = device.vkAllocateCommandBuffers(cmdinfo, (SegmentAllocator)scope, scope);
+ }
+ }
+
+ // parameterise as init_image?
+ void init_depth() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ int format = VK_FORMAT_D16_UNORM;
+ VkMemoryRequirements req = VkMemoryRequirements.create(frame);
+ VkImageCreateInfo imageinfo = VkImageCreateInfo.create(frame, 0,
+ VK_IMAGE_TYPE_2D,
+ format,
+ 1,
+ 1,
+ NUM_SAMPLES,
+ 0,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ VK_SHARING_MODE_EXCLUSIVE,
+ null,
+ VK_IMAGE_LAYOUT_UNDEFINED);
+ imageinfo.getExtent().setWidth(width);
+ imageinfo.getExtent().setHeight(height);
+ imageinfo.getExtent().setDepth(1);
+
+ depthImage = device.vkCreateImage(imageinfo, scope);
+
+ device.vkGetImageMemoryRequirements(depthImage, req);
+ VkMemoryAllocateInfo alloc = VkMemoryAllocateInfo.create(frame,
+ req.getSize(),
+ find_memory_type(memory_properties, req.getMemoryTypeBits(), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
+
+ depthMemory = device.vkAllocateMemory(alloc, scope);
+
+ device.vkBindImageMemory(depthImage, depthMemory, 0);
+
+ VkImageViewCreateInfo viewinfo = VkImageViewCreateInfo.create(frame, 0,
+ depthImage,
+ VK_IMAGE_VIEW_TYPE_2D,
+ VK_FORMAT_D16_UNORM);
+
+ VkComponentMapping components = viewinfo.getComponents();
+ components.setR(VK_COMPONENT_SWIZZLE_R);
+ components.setG(VK_COMPONENT_SWIZZLE_G);
+ components.setB(VK_COMPONENT_SWIZZLE_B);
+ components.setA(VK_COMPONENT_SWIZZLE_A);
+ VkImageSubresourceRange subresourceRange = viewinfo.getSubresourceRange();
+ subresourceRange.setAspectMask(VK_IMAGE_ASPECT_DEPTH_BIT);
+ subresourceRange.setLevelCount(1);
+ subresourceRange.setLayerCount(1);
+
+ depthView = device.vkCreateImageView(viewinfo, scope);
+
+ depthFormat = format;
+ }
+ }
+
+ void init_uniform() throws Exception {
+ 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));
+ }
+
+ void init_descriptor() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ HandleArray<VkDescriptorSetLayout> layout_table = VkDescriptorSetLayout.createArray(1, frame);
+ VkDescriptorSetLayoutBinding layout_binding = VkDescriptorSetLayoutBinding.create(frame,
+ 0,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ null);
+ VkDescriptorSetLayoutCreateInfo descriptor_layout = VkDescriptorSetLayoutCreateInfo.create(frame,
+ 0,
+ layout_binding);
+
+ desc_layout = device.vkCreateDescriptorSetLayout(descriptor_layout, scope);
+ layout_table.setAtIndex(0, desc_layout);
+
+ VkPipelineLayoutCreateInfo pipeline_info = VkPipelineLayoutCreateInfo.create(frame,
+ 0,
+ //1,
+ layout_table,
+ null);
+
+ pipeline_layout = device.vkCreatePipelineLayout(pipeline_info, scope);
+
+ VkDescriptorPoolSize type_count = VkDescriptorPoolSize.create(frame,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1);
+
+ VkDescriptorPoolCreateInfo descriptor_pool = VkDescriptorPoolCreateInfo.create(frame,
+ 0,
+ 1,
+ type_count);
+
+ desc_pool = device.vkCreateDescriptorPool(descriptor_pool, scope);
+
+ VkDescriptorSetAllocateInfo alloc_info = VkDescriptorSetAllocateInfo.create(frame,
+ desc_pool,
+ //1,
+ layout_table);
+
+ System.out.println(alloc_info);
+
+ desc_set = device.vkAllocateDescriptorSets(alloc_info, (SegmentAllocator)scope);
+
+ VkDescriptorBufferInfo uniformInfo = VkDescriptorBufferInfo.create(frame, uniform.buffer, 0, uniform.size);
+ VkWriteDescriptorSet writes = VkWriteDescriptorSet.create(frame,
+ desc_set.getAtIndex(0),
+ 0,
+ 0,
+ 1,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ null,
+ uniformInfo,
+ null);
+
+ device.vkUpdateDescriptorSets(writes, null);
+ }
+ }
+
+ void init_render() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ VkAttachmentDescription attachments = VkAttachmentDescription.createArray(2, frame);
+
+ attachments.setFormat(chainImageFormat);
+ attachments.setSamples(NUM_SAMPLES);
+ attachments.setLoadOp(VK_ATTACHMENT_LOAD_OP_CLEAR);
+ attachments.setStoreOp(VK_ATTACHMENT_STORE_OP_STORE);
+ attachments.setStencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE);
+ attachments.setStencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE);
+ attachments.setInitialLayout(VK_IMAGE_LAYOUT_UNDEFINED);
+ attachments.setFinalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
+ attachments.setFlags(0);
+
+ attachments.setFormatAtIndex(1, depthFormat);
+ attachments.setSamplesAtIndex(1, NUM_SAMPLES);
+ attachments.setLoadOpAtIndex(1, VK_ATTACHMENT_LOAD_OP_CLEAR);
+ attachments.setStoreOpAtIndex(1, VK_ATTACHMENT_STORE_OP_STORE);
+ attachments.setStencilLoadOpAtIndex(1, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
+ attachments.setStencilStoreOpAtIndex(1, VK_ATTACHMENT_STORE_OP_DONT_CARE);
+ attachments.setInitialLayoutAtIndex(1, VK_IMAGE_LAYOUT_UNDEFINED);
+ attachments.setFinalLayoutAtIndex(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+ attachments.setFlagsAtIndex(1, 0);
+
+ VkAttachmentReference color_reference = VkAttachmentReference.create(frame,
+ 0,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+
+ VkAttachmentReference depth_reference = VkAttachmentReference.create(frame,
+ 1,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+
+ VkSubpassDescription subpass = VkSubpassDescription.create(frame,
+ 0,
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ null,
+ 1,
+ color_reference,
+ null,
+ depth_reference,
+ null);
+
+ VkRenderPassCreateInfo rp_info = VkRenderPassCreateInfo.create(frame,
+ 0,
+ //(int)attachments.length(),
+ attachments,
+ subpass,
+ null);
+
+ render_pass = device.vkCreateRenderPass(rp_info, scope);
+ }
+ }
+
+ void init_framebuffer() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ HandleArray<VkImageView> attachments = VkImageView.createArray(2, frame);
+
+ attachments.setAtIndex(1, depthView);
+
+ // FIXME: I don't think i want lenghts implied for types tbh
+ VkFramebufferCreateInfo fb_info = VkFramebufferCreateInfo.create(frame,
+ 0,
+ render_pass,
+ //2,
+ attachments,
+ width,
+ height,
+ 1);
+
+ framebuffers = VkFramebuffer.createArray(chainImage.length(), (SegmentAllocator)scope);
+ for (int i = 0; i < chainImage.size(); i++) {
+ attachments.setAtIndex(0, chainImageView.get(i));
+ framebuffers.setAtIndex(i, device.vkCreateFramebuffer(fb_info, scope));
+ System.out.printf("framebuffer[%d] = %s\n", i, framebuffers.getAtIndex(i));
+ }
+ }
+ }
+
+ void init_vertexbuffer() throws Exception {
+ try (Frame frame = Frame.frame()) {
+ vertex = init_buffer(Cube.data.length * 4, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, MemorySegment.ofArray(Cube.data));
+
+ vertexBuffer.setAtIndex(0, vertex.buffer);
+
+ /* ***************************************** */
+ vi_binding.setBinding(0);
+ vi_binding.setInputRate(VK_VERTEX_INPUT_RATE_VERTEX);
+ vi_binding.setStride(Cube.dataStride);
+
+ vi_attribs.setBinding(0);
+ vi_attribs.setLocation(0);
+ vi_attribs.setFormat(VK_FORMAT_R32G32B32A32_SFLOAT);
+ vi_attribs.setOffset(0);
+ vi_attribs.setBindingAtIndex(1, 0);
+ vi_attribs.setLocationAtIndex(1, 1);
+ vi_attribs.setFormatAtIndex(1, VK_FORMAT_R32G32B32A32_SFLOAT);
+ vi_attribs.setOffsetAtIndex(1, 16);
+ }
+ }
+
+ void init_pipeline() throws Exception {
+ int res;
+ try (Frame frame = Frame.frame()) {
+ IntArray dynamicStateEnables = IntArray.create(frame,
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR);
+
+ VkPipelineDynamicStateCreateInfo dynamicState = VkPipelineDynamicStateCreateInfo.create(frame,
+ 0, dynamicStateEnables);
+
+ VkPipelineVertexInputStateCreateInfo vi = VkPipelineVertexInputStateCreateInfo.create(frame,
+ 0,
+ vi_binding,
+ vi_attribs);
+
+ VkPipelineInputAssemblyStateCreateInfo ia = VkPipelineInputAssemblyStateCreateInfo.create(frame,
+ 0,
+ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+ 0);
+
+ VkPipelineRasterizationStateCreateInfo rs = VkPipelineRasterizationStateCreateInfo.create(frame,
+ 0,
+ VK_TRUE,
+ VK_FALSE,
+ VK_POLYGON_MODE_FILL,
+ VK_CULL_MODE_BACK_BIT,
+ VK_FRONT_FACE_CLOCKWISE,
+ VK_FALSE,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f);
+
+ VkPipelineColorBlendAttachmentState att_state = VkPipelineColorBlendAttachmentState.create(frame,
+ VK_FALSE,
+ VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_OP_ADD,
+ VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_FACTOR_ZERO,
+ VK_BLEND_OP_ADD,
+ 0xf);
+
+ VkPipelineColorBlendStateCreateInfo cb = VkPipelineColorBlendStateCreateInfo.create(frame,
+ 0,
+ VK_FALSE,
+ VK_LOGIC_OP_NO_OP,
+ att_state,
+ 1.0f, 1.0f, 1.0f, 1.0f);
+
+ VkPipelineViewportStateCreateInfo vp = VkPipelineViewportStateCreateInfo.create(frame,
+ 0,
+ 1, null,
+ 1, null);
+
+ VkPipelineDepthStencilStateCreateInfo ds = VkPipelineDepthStencilStateCreateInfo.create(frame,
+ 0,
+ VK_TRUE,
+ VK_TRUE,
+ VK_COMPARE_OP_LESS_OR_EQUAL,
+ VK_FALSE,
+ VK_FALSE,
+ 0.0f,
+ 0.0f);
+ VkStencilOpState back = ds.getBack();
+
+ back.setFailOp(VK_STENCIL_OP_KEEP);
+ back.setPassOp(VK_STENCIL_OP_KEEP);
+ back.setCompareOp(VK_COMPARE_OP_ALWAYS);
+ back.setCompareMask(0);
+ back.setReference(0);
+ back.setDepthFailOp(VK_STENCIL_OP_KEEP);
+ back.setWriteMask(0);
+
+ VkStencilOpState front = ds.getFront();
+
+ front.setFailOp(VK_STENCIL_OP_KEEP);
+ front.setPassOp(VK_STENCIL_OP_KEEP);
+ front.setCompareOp(VK_COMPARE_OP_ALWAYS);
+ front.setCompareMask(0);
+ front.setReference(0);
+ front.setDepthFailOp(VK_STENCIL_OP_KEEP);
+ front.setWriteMask(0);
+
+ VkPipelineMultisampleStateCreateInfo ms = VkPipelineMultisampleStateCreateInfo.create(frame,
+ 0,
+ NUM_SAMPLES,
+ 0, //.sampleShadingEnable = VK_FALSE,
+ 0.0f,
+ null,
+ 0, //.alphaToCoverageEnable = VK_FALSE,
+ 0 //.alphaToOneEnable = VK_FALSE,
+ );
+
+ VkShaderModuleCreateInfo vsInfo = VkShaderModuleCreateInfo.create(frame,
+ 0,
+ cube_vs.length() * 4,
+ cube_vs);
+ VkShaderModuleCreateInfo fsInfo = VkShaderModuleCreateInfo.create(frame,
+ 0,
+ cube_fs.length() * 4,
+ cube_fs);
+
+ shader.setAtIndex(0, device.vkCreateShaderModule(vsInfo, scope));
+ shader.setAtIndex(1, device.vkCreateShaderModule(fsInfo, scope));
+
+ VkPipelineShaderStageCreateInfo shaderStages = VkPipelineShaderStageCreateInfo.createArray(2, (SegmentAllocator)scope);
+
+ // FIXME: createArray should initialise this
+ shaderStages.setSType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
+ shaderStages.setStage(VK_SHADER_STAGE_VERTEX_BIT);
+ shaderStages.setName("main", (SegmentAllocator)scope);
+ shaderStages.setModule(shader.get(0));
+
+ shaderStages.setSTypeAtIndex(1, VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
+ shaderStages.setStageAtIndex(1, VK_SHADER_STAGE_FRAGMENT_BIT);
+ shaderStages.setNameAtIndex(1, "main", (SegmentAllocator)scope);
+ shaderStages.setModuleAtIndex(1, shader.get(1));
+
+ VkGraphicsPipelineCreateInfo pipeline = VkGraphicsPipelineCreateInfo.create(frame,
+ 0,
+ //2, shaderStages,
+ shaderStages,
+ vi,
+ ia,
+ null,
+ vp,
+ rs,
+ ms,
+ ds,
+ cb,
+ dynamicState,
+ pipeline_layout,
+ render_pass,
+ 0,
+ null,
+ 0);
+
+ res = device.vkCreateGraphicsPipelines(null, pipeline, this.pipeline);
+
+ VkSemaphoreCreateInfo seminfo = VkSemaphoreCreateInfo.create(frame, 0);
+ chainSemaphore = device.vkCreateSemaphore(seminfo, scope);
+
+ VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.create(frame, 0);
+ drawFence = device.vkCreateFence(fenceInfo, scope);
+ }
+ }
+
+
+ void execute_begin_command_buffer() throws Exception {
+ /* DEPENDS on init_command() */
+ try (Frame frame = Frame.frame()) {
+ VkCommandBufferBeginInfo cmd_buf_info = VkCommandBufferBeginInfo.create(frame,
+ 0,
+ null);
+
+ cmd.getAtIndex(0).vkBeginCommandBuffer(cmd_buf_info);
+ }
+ }
+
+ void execute_end_command_buffer() throws Exception {
+ cmd.getAtIndex(0).vkEndCommandBuffer();
+ }
+
+ final static long FENCE_TIMEOUT = 100000000;
+
+ void execute_queue_command_buffer() throws Exception {
+ int res;
+
+ /* Queue the command buffer for execution */
+ /* FIXME: frame shoudl provide or take explicit scope */
+ try (ResourceScope scope = ResourceScope.newConfinedScope();
+ Frame frame = Frame.frame()) {
+ IntArray pipe_stage_flags = IntArray.create(frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.create(frame, 0);
+ HandleArray<VkFence> fences = VkFence.createArray(1, frame);
+
+ fences.setAtIndex(0, device.vkCreateFence(fenceInfo, scope));
+
+ VkSubmitInfo submit_info = VkSubmitInfo.create(frame,
+ 1, null, pipe_stage_flags,
+ cmd,
+ null);
+
+ graphics_queue.vkQueueSubmit(submit_info, drawFence);
+
+ do {
+ res = device.vkWaitForFences(fences, 1, FENCE_TIMEOUT);
+ } while (res == VK_TIMEOUT);
+
+ device.vkDestroyFence(fences.getAtIndex(0));
+ }
+ }
+
+ void cmd_viewport() {
+ try (Frame frame = Frame.frame()) {
+ VkCommandBuffer cmd = this.cmd.getAtIndex(0);
+ VkViewport viewport = VkViewport.create(frame,
+ 0, 0, width, height, 0.0f, 1.0f);
+ cmd.vkCmdSetViewport(0, 1, viewport);
+ }
+ }
+
+ void cmd_scissors() {
+ try (Frame frame = Frame.frame()) {
+ VkCommandBuffer cmd = this.cmd.getAtIndex(0);
+ VkRect2D scissor = VkRect2D.create(frame);
+ VkExtent2D extent = scissor.getExtent();
+
+ extent.setWidth(width);
+ extent.setHeight(height);
+
+ cmd.vkCmdSetScissor(0, 1, scissor);
+ }
+ }
+
+ void cmd_paint() throws Exception {
+ int res;
+ try (Frame frame = Frame.frame()) {
+ int chainIndex;
+ IntArray chainIndices = IntArray.createArray(1, frame);
+ VkCommandBuffer cmd = this.cmd.getAtIndex(0);
+
+ device.vkAcquireNextImageKHR(chain, ~0L, chainSemaphore, null, chainIndices);
+ chainIndex = chainIndices.getAtIndex(0);
+ LongArray offsets = LongArray.createArray(1, frame);
+
+ VkClearValue clear_values = VkClearValue.createArray(2, frame);
+ FloatArray col = clear_values.getColor().getFloat32();
+ col.setAtIndex(0, 0.2f);
+ col.setAtIndex(1, 0.2f);
+ col.setAtIndex(2, 0.2f);
+ col.setAtIndex(3, 0.2f);
+ VkClearDepthStencilValue depthStencil = clear_values.getAtIndex(1).getDepthStencil();
+ depthStencil.setDepth(1.0f);
+ depthStencil.setStencil(0);
+
+ System.out.printf("render framebuffer[%d] = %s\n", chainIndex, framebuffers.getAtIndex(chainIndex));
+
+ VkRenderPassBeginInfo rp_begin = VkRenderPassBeginInfo.create(frame,
+ render_pass,
+ framebuffers.getAtIndex(chainIndex),
+ clear_values);
+ VkExtent2D extent = rp_begin.getRenderArea().getExtent();
+ extent.setWidth(width);
+ extent.setHeight(height);
+
+ cmd.vkCmdBeginRenderPass(rp_begin, VK_SUBPASS_CONTENTS_INLINE);
+
+ cmd.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getAtIndex(0));
+ cmd.vkCmdBindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, NUM_DESCRIPTOR_SETS, desc_set, 0, null);
+ cmd.vkCmdBindVertexBuffers(0, 1, vertexBuffer, offsets);
+
+ cmd_viewport();
+ cmd_scissors();
+
+ cmd.vkCmdDraw(12 * 3, 1, 0, 0);
+ cmd.vkCmdEndRenderPass();
+
+ cmd.vkEndCommandBuffer();
+
+ IntArray pipe_stage_flags = IntArray.create(frame, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ HandleArray<VkSemaphore> semaphores = VkSemaphore.createArray(1, frame);//, chainSemaphore, scope);
+
+ semaphores.setAtIndex(0, chainSemaphore);
+
+ VkSubmitInfo submit_info = VkSubmitInfo.create(frame,
+ 1, semaphores, pipe_stage_flags,
+ this.cmd,
+ null);
+
+ HandleArray<VkFence> fences = VkFence.createArray(1, frame);
+
+ fences.setAtIndex(0, drawFence);
+
+ // Queue the command buffer for execution
+ device.vkResetFences(fences);
+
+ graphics_queue.vkQueueSubmit(submit_info, drawFence);
+
+ // Make sure command buffer is finished before presenting
+ do {
+ res = device.vkWaitForFences(fences, VK_TRUE, FENCE_TIMEOUT);
+ } while (res == VK_TIMEOUT);
+
+ // Now present the image in the window
+ HandleArray<VkSwapchainKHR> chains = VkSwapchainKHR.createArray(1, frame);
+ chains.setAtIndex(0, chain);
+ VkPresentInfoKHR present = VkPresentInfoKHR.create(frame,
+ null,
+ 1,
+ chains,
+ chainIndices,
+ null);
+
+ present_queue.vkQueuePresentKHR(present);
+ }
+ }
+
+ /**
+ * Buffers are created in three steps:
+ * 1) create buffer, specifying usage and size
+ * 2) allocate memory based on memory requirements
+ * 3) bind memory
+ *
+ */
+ BufferMemory init_buffer(long dataSize, int usage, int properties, MemorySegment init) throws Exception {
+ try (Frame frame = Frame.frame()) {
+ VkMemoryRequirements req = VkMemoryRequirements.create(frame);
+ VkBufferCreateInfo buf_info = VkBufferCreateInfo.create(frame,
+ 0,
+ dataSize,
+ usage,
+ VK_SHARING_MODE_EXCLUSIVE,
+ //0,
+ null);
+
+ VkBuffer buffer = device.vkCreateBuffer(buf_info, scope);
+
+ device.vkGetBufferMemoryRequirements(buffer, req);
+
+ VkMemoryAllocateInfo alloc = VkMemoryAllocateInfo.create(frame,
+ req.getSize(),
+ find_memory_type(memory_properties, req.getMemoryTypeBits(), properties));
+
+ VkDeviceMemory memory = device.vkAllocateMemory(alloc, scope);
+
+ if (init != null) {
+ MemorySegment mem = device.vkMapMemory(memory, 0, dataSize, 0, scope);
+ mem.copyFrom(init);
+ device.vkUnmapMemory(memory);
+ }
+
+ device.vkBindBufferMemory(buffer, memory, 0);
+
+ return new BufferMemory(buffer, memory, dataSize);
+ }
+ }
+
+ void shutdown() {
+ device.vkDestroyFence(drawFence);
+ device.vkDestroySemaphore(chainSemaphore);
+
+ device.vkDestroyPipeline(pipeline.getAtIndex(0));
+ for (int i=0;i<shader.size();i++)
+ device.vkDestroyShaderModule(shader.getAtIndex(i));
+
+ vertex.free(device);
+ uniform.free(device);
+
+ for (int i=0;i<framebuffers.size();i++)
+ device.vkDestroyFramebuffer(framebuffers.getAtIndex(i));
+
+ device.vkDestroyRenderPass(render_pass);
+
+ device.vkDestroyDescriptorPool(desc_pool);
+ device.vkDestroyPipelineLayout(pipeline_layout);
+ device.vkDestroyDescriptorSetLayout(desc_layout);
+
+ device.vkDestroyImageView(depthView);
+ device.vkFreeMemory(depthMemory);
+ device.vkDestroyImage(depthImage);
+
+ for (int i = 0; i < chainImageView.size(); i++)
+ device.vkDestroyImageView(chainImageView.getAtIndex(i));
+
+ device.vkDestroySwapchainKHR(chain);
+
+ device.vkDestroyCommandPool(cmd_pool);
+ device.vkDestroyDevice();
+
+ instance.vkDestroySurfaceKHR(surface);
+
+ if (logger != null)
+ instance.vkDestroyDebugUtilsMessengerEXT(logger);
+ instance.vkDestroyInstance();
+ }
+
+ IntArray loadSPIRV0(String name) throws IOException {
+ // hmm any way to just load this directly?
+ try (InputStream is = TestCube.class.getResourceAsStream(name)) {
+ ByteBuffer bb = ByteBuffer.allocateDirect(8192).order(ByteOrder.nativeOrder());
+ int length = Channels.newChannel(is).read(bb);
+
+ bb.position(0);
+ bb.limit(length);
+
+ return IntArray.create(MemorySegment.ofByteBuffer(bb));
+ }
+ }
+
+ IntArray loadSPIRV(String name) throws IOException {
+ try (InputStream is = TestCube.class.getResourceAsStream(name)) {
+ MemorySegment seg = ((SegmentAllocator)scope).allocateArray(Memory.INT, 2048);
+ int length = Channels.newChannel(is).read(seg.asByteBuffer());
+
+ return IntArray.create(seg.asSlice(0, length));
+ }
+ }
+ IntArray loadSPIRV(String name, SegmentAllocator alloc) throws IOException {
+ try (InputStream is = TestCube.class.getResourceAsStream(name)) {
+ MemorySegment seg = alloc.allocateArray(Memory.INT, 2048);
+ int length = Channels.newChannel(is).read(seg.asByteBuffer());
+
+ return IntArray.create(seg.asSlice(0, length));
+ }
+ }
+
+ /**
+ * This finds the memory type index for the memory on a specific device.
+ */
+ static int find_memory_type(VkPhysicalDeviceMemoryProperties memory, int typeMask, int query) {
+ VkMemoryType mtypes = memory.getMemoryTypes();
+
+ for (int i = 0; i < memory.getMemoryTypeCount(); i++) {
+ if (((1 << i) & typeMask) != 0 && ((mtypes.getAtIndex(i).getPropertyFlags() & query) == query))
+ return i;
+ }
+ return -1;
+ }
+
+ public static int VK_MAKE_API_VERSION(int variant, int major, int minor, int patch) {
+ return (variant << 29) | (major << 22) | (minor << 12) | patch;
+ }
+
+ static int clampi(int v, int min, int max) {
+ return v < min ? min : v < max ? v : max;
+ }
+
+ void init_matrices() {
+ float eye[] = new float[] {-5, 3, -10};
+ float centre[] = new float[] {0, 0, 0};
+ float up[] = new float[] {0, -1, 0};
+ float t0[] = new float[16], t1[] = new float[16];
+
+ perspective(projection, (float)(Math.PI * 0.25), 1.0f, 0.1f, 100.0f);
+ lookAt(view, eye, centre, up);
+ identity4f(model);
+ mult4x4f(t0, clip, projection);
+ mult4x4f(t1, t0, view);
+ mult4x4f(mvp, t1, model);
+ }
+
+ void demo() throws Exception {
+ cube_vs = loadSPIRV("cube_vs.bin");
+ cube_fs = loadSPIRV("cube_fs.bin");
+
+ init_matrices();
+
+ init_instance();
+ init_debug();
+
+ init_surface();
+ init_device();
+ init_device_queue();
+ init_command();
+ init_depth();
+ init_uniform();
+
+ init_descriptor();
+ init_render();
+ init_framebuffer();
+ init_vertexbuffer();
+ init_pipeline();
+
+ execute_begin_command_buffer();
+
+ cmd_paint();
+
+ System.out.println("behold the prize!");
+ Thread.sleep(2000);
+
+ shutdown();
+ }
+
+ public static void main(String[] args) throws Throwable {
+ System.loadLibrary("vulkan");
+ System.loadLibrary("X11");
+
+ new TestCube().demo();
+ }
+}
/* Bind the compute operation and data */
commandBuffers.get(0).vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.get(0));
- commandBuffers.get(0).vkCmdBindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, descriptorSets, null);
+ commandBuffers.get(0).vkCmdBindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, descriptorSets, 0, null);
/* Run it */
commandBuffers.get(0).vkCmdDispatch(WIDTH, HEIGHT, 1);
* errors: {errorcodes}
*/
public {static}{java-result} {rename}(
- {java-arguments}) {
+ {java-arg}) {
{native-result-define}
try {create-frame}{
{native-init}
- {native-result-assign}{name}$FH.invokeExact({invoke-arguments});
+ {native-result-assign}{name}$FH.invokeExact({invoke-arg});
{result-test}{
{java-result-assign}
{java-result-return}
* errors: {errorcodes}
*/
public {static}{java-result} {rename}(
- {java-arguments}) {
+ {java-arg}) {
{native-result-define}
try {create-frame}{
{native-init}
- {native-result-assign}{name}$FH.invokeExact({query-arguments});
+ {native-result-assign}{name}$FH.invokeExact({query-arg});
{result-test}{
{query-init}
- {native-result-assign}{name}$FH.invokeExact({invoke-arguments});
+ {native-result-assign}{name}$FH.invokeExact({invoke-arg});
{java-result-assign}
{java-result-return}
}
* errors: {errorcodes}
*/
public {static}{java-result} {rename}(
- {java-arguments}) {
+ {java-arg}) {
{native-result-define}
try {create-frame}{
{native-init}
- {native-result-assign}{name}$DH.invokeExact(dispatch.{name}$NS, {invoke-arguments});
+ {native-result-assign}{name}$DH.invokeExact(dispatch.{name}$NS, {invoke-arg});
{result-test}{
{java-result-assign}
{java-result-return}
* errors: {errorcodes}
*/
public {static}{java-result} {rename}(
- {java-arguments}) {
+ {java-arg}) {
{native-result-define}
try {create-frame}{
{native-init}
- {native-result-assign}{name}$DH.invokeExact(dispatch.{name}$NS, {query-arguments});
+ {native-result-assign}{name}$DH.invokeExact(dispatch.{name}$NS, {query-arg});
{result-test}{
{query-init}
- {native-result-assign}{name}$DH.invokeExact(dispatch.{name}$NS, {invoke-arguments});
+ {native-result-assign}{name}$DH.invokeExact(dispatch.{name}$NS, {invoke-arg});
{java-result-assign}
{java-result-return}
}
# common parts for funcpointer
code funcpointer {
common {{
- public {java-result} call({java-arguments});
+ public {java-result} call({java-arg});
public final static FunctionDescriptor DESCRIPTOR =
{function-descriptor};
upcall {{
public static FunctionPointer<{rename}> upcall({rename} target$, ResourceScope scope$) {
interface Trampoline {
- {native-result} call({native-arguments});
+ {native-result} call({native-arg});
}
- Trampoline trampoline = ({native-arguments}) -> {
+ Trampoline trampoline = ({native-arg}) -> {
// frame? scope?
try {trampoline-scope} {
{trampoline-result-define}
- {trampoline-result-assign}target$.call({trampoline-arguments});
+ {trampoline-result-assign}target$.call({trampoline-arg});
{trampoline-result-return}
} catch (Throwable t) {
throw new RuntimeException(t);
typei {{ {baseType} }}
}
-type struct inline {
- type {{ {baseType} }}
- layout {{ {baseType}.LAYOUT }}
-}
+#type struct inline {
+# type {{ {baseType} }}
+# layout {{ {baseType}.LAYOUT }}
+#}
type struct* pointer trampoline-scope {
type {{ {baseType} }}
type uint32_t*-length-query uint32_t*-length need-alloc {
java-arg {{ }}
- invoke-arg {{ {name} }}
+ invoke-arg {{ (Addressable){name}.address() }}
query-arg {{ (Addressable)MemoryAddress.NULL }}
java-result {{ {type} }}
java-result-return {{ return {name}; }}
}
+# A couple of very special cases
type VkCommandBuffer-alloc handle*-alloc need-scope need-alloc {
native-init {{
{type} {name} = {typei}.createArray(
type VkDescriptorSet-alloc handle*-alloc need-alloc {
native-init {{
{type} {name} = {typei}.createArray(
- (int)VkCommandBufferAllocateInfo.commandBufferCount$VH.get(pAllocateInfo.segment),
+ (int)VkDescriptorSetAllocateInfo.descriptorSetCount$VH.get(pAllocateInfo.segment),
alloc$);
}}
}
vkMapMemory device=type:instance ppData=type:vkMapMemory-output;
+ # forces ignoring of lengths, maybe need to do it for all vkCmd
+ #vkCmdSetScissor commandBuffer=type:instance;
+ #vkCmdSetViewport commandBuffer=type:instance;
+ #vkCmdBindDescriptorSets commandBuffer=type:instance;
+
# Don't need userData
PFN_vkDebugUtilsMessengerCallbackEXT pUserData=type:void*-ignore;
PFN_vkDebugReportCallbackEXT pUserData=type:void*-ignore;
},
};
-# all seen types for dev only
-my $all = {};
-
# ###################################################################### #
-my $vk = new vulkan();
+my $sys = {};
+
+$sys->{output} = 'bin/gen/notzed.vulkan/classes';
+$sys->{package} = 'vulkan';
+$sys->{verbose} = 0;
+
+my $vk = new vulkan($sys);
my $api = $vk->buildFeatures(
[ 'VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2' ],
#'wayland',
'xcb' ]);
-my $sys = {};
-
-$sys->{output} = 'bin/gen/notzed.vulkan/classes';
-$sys->{package} = 'vulkan';
-$sys->{verbose} = 0;
-
my $structTypes = loadTypes($api, 'struct-types.api');
my $commandTypes = loadTypes($api, 'command-types.api');
$m->{deref} .= '-ignore';
}
- if ($m->{lengthfor}) {
+ # All the vkCmd commands shouldn't imply any array lengths, maybe nothing should really?
+ if ($first->{baseType} ne 'VkCommandBuffer' && $m->{lengthfor}) {
my $nstar = $m->{deref} =~ tr/*/*/;
if ($nstar == 0) {
die "No '$m->{deref}-length' type ".Dumper($s) if !defined $types->{$m->{deref}.'-length'};
#print Dumper({ types=>$types, templates=>$templates });
#print Dumper($vk);
-open(my $f, '>', 'types.pm');
-print $f Dumper($commandTypes, $structTypes);
-close $f;
-
-if (1) {
-
- if (0) {
- open(my $f, '>', 'api.pm');
- print $f Dumper($api);
- close $f;
- die;
- }
-
- if (1) {
- open(my $f, '>', 'data.pm');
- print $f Dumper({
- 'handles' => $api->{handles},
- 'types' => $api->{types},
- 'commands' => $api->{commands},
- 'funcpointers' => $api->{funcpointers},
- });
- close $f;
- }
-
- if (0) {
- my $f = openOutput($sys, "API");
-
- print $f "package vulkan;\n";
- print $f "import jdk.incubator.foreign.*;\n";
- print $f "import java.lang.invoke.*;\n";
- print $f "import au.notzed.nativez.*;\n";
- print $f "public class API {\n";
- print $f "MemoryAddress self;\n";
-
- foreach my $c (values %{$api->{commands}}) {
- die if ($c->{alias});
- #print "$c->{name}\n";
- print $f formatFunction($api, $commandTypes, $c)."\n";
- #print formatFunctionDescriptor($commandTypes, $c)."\n";
- }
- print $f "}\n";
- closeOutput($sys, "API", $f);
- }
-
- exportEnums($vk, $api, 'VkConstants');
-
- # dump out the extension function tables
- {
- my $f = openOutput($sys, 'DispatchInstance');
- my $template = $structTypes->{templates}->{dispatch};
- my @init = ();
- my @fieldInit = ();
-
- foreach my $k (sort keys %{$api->{commands}}) {
- my $c = $api->{commands}->{$k};
-
- next if !defined($c->{extensions});
-
- push @fieldInit, code::formatTemplate($template->{'field-init'}, $c);
- push @init, code::formatTemplate($template->{'init'}, $c);
-
- }
-
- my $vars = {
- package => 'vulkan',
- Name => 'DispatchInstance',
- init => join("\n\t\t", @init),
- 'field-init' => join("\n\t", @fieldInit),
- };
- print $f code::formatTemplateStream($template->{class}, $vars);
-
- closeOutput($sys, 'DispatchInstance', $f);
- }
-
-
-
- foreach my $k (sort keys %{$api->{types}}) {
- my $s = $api->{data}->{$k};
-
- die if !defined $s;
- next if $s->{alias};
-
- my $override = $structTypes->{overrides}->{$s->{name}};
-
- next if $override->{ignore};
-
- my $f = openOutput($sys, $s->{Name});
- print $f formatStruct($vk, $api, $s);
- closeOutput($sys, $s->{Name}, $f);
- }
+if (0) {
+ open(my $f, '>', 'types.pm');
+ print $f Dumper($commandTypes, $structTypes);
+ close $f;
+}
- foreach my $k (sort keys %{$api->{handles}}) {
- my $s = $api->{data}->{$k};
+if (0) {
+ open(my $f, '>', 'api.pm');
+ print $f Dumper($api);
+ close $f;
+ die;
+}
- die if !defined $s;
- next if $s->{alias};
+if (0) {
+ open(my $f, '>', 'data.pm');
+ print $f Dumper({
+ 'handles' => $api->{handles},
+ 'types' => $api->{types},
+ 'commands' => $api->{commands},
+ 'funcpointers' => $api->{funcpointers},
+ });
+ close $f;
+}
- my $f = openOutput($sys, $s->{name});
- print $f formatHandle($vk, $api, $s);
- closeOutput($sys, $s->{name}, $f);
- }
+exportEnums($vk, $api, 'VkConstants');
- foreach my $k (sort keys %{$api->{funcpointers}}) {
- my $s = $api->{data}->{$k};
+# dump out the extension function tables
+{
+ my $f = openOutput($sys, 'DispatchInstance');
+ my $template = $structTypes->{templates}->{dispatch};
+ my @init = ();
+ my @fieldInit = ();
- die if !defined $s;
- next if $s->{alias};
+ foreach my $k (sort keys %{$api->{commands}}) {
+ my $c = $api->{commands}->{$k};
- my $override = $commandTypes->{overrides}->{$s->{name}};
+ next if !defined($c->{extensions});
- next if $override->{ignore};
+ push @fieldInit, code::formatTemplate($template->{'field-init'}, $c);
+ push @init, code::formatTemplate($template->{'init'}, $c);
- my $f = openOutput($sys, $s->{name});
- print $f formatFunctionPointer($vk, $api, $s);
- closeOutput($sys, $s->{name}, $f);
}
+ my $vars = {
+ package => 'vulkan',
+ Name => 'DispatchInstance',
+ init => join("\n\t\t", @init),
+ 'field-init' => join("\n\t", @fieldInit),
+ };
+ print $f code::formatTemplateStream($template->{class}, $vars);
- exit 0;
-
- #print Dumper (grep { !defined $_->{items} } values %{$api->{enums}});
-
- #print Dumper($api->{data});
-
- print "Unique Types:\n";
- foreach my $k (sort keys %$all) {
- print "$k\n";
- }
+ closeOutput($sys, 'DispatchInstance', $f);
+}
- exit 0;
+# structs and unions
+foreach my $k (sort keys %{$api->{types}}) {
+ my $s = $api->{data}->{$k};
- foreach my $k (sort keys %{$api->{commands}}) {
- my $c = $api->{commands}->{$k};
+ die if !defined $s;
+ next if $s->{alias};
- #print Dumper ($c);
+ my $override = $structTypes->{overrides}->{$s->{name}};
- foreach my $m ($c->{proto}, @{$c->{items}}) {
- my $t = $vk->{data}->{$m->{baseType}};
+ next if $override->{ignore};
- die if !defined $m->{baseType};
- print "? $m->{baseType} ($k $m->{name}\n" if !defined($t);
+ my $f = openOutput($sys, $s->{Name});
+ print $f formatStruct($vk, $api, $s);
+ closeOutput($sys, $s->{Name}, $f);
+}
- while ($t->{alias}) {
- print "Alias: $t->{name} -> $t->{alias}\n";
- $t = $vk->{data}->{$t->{alias}};
- }
- }
- }
+# handles
+foreach my $k (sort keys %{$api->{handles}}) {
+ my $s = $api->{data}->{$k};
-} else {
+ die if !defined $s;
+ next if $s->{alias};
-foreach my $k (sort keys %{$vk->{index}}) {
- print "$k\n";
+ my $f = openOutput($sys, $s->{name});
+ print $f formatHandle($vk, $api, $s);
+ closeOutput($sys, $s->{name}, $f);
}
-my $masks = {};
-my $enums = {};
+# upcalls
+foreach my $k (sort keys %{$api->{funcpointers}}) {
+ my $s = $api->{data}->{$k};
-foreach my $k (sort keys %{$vk->{types}}) {
- my $s = $vk->{types}->{$k};
- #print Dumper($s);
- foreach my $m (@{$s->{items}}) {
- my $t = $vk->{data}->{$m->{baseType}};
+ die if !defined $s;
+ next if $s->{alias};
- die if !defined $m->{baseType};
- print "? $m->{baseType} ($k $m->{name}\n" if !defined($t);
+ my $override = $commandTypes->{overrides}->{$s->{name}};
- while ($t->{alias}) {
- print "Alias: $t->{name} -> $t->{alias}\n";
- $t = $vk->{data}->{$t->{alias}};
- }
+ next if $override->{ignore};
- $masks->{$t->{name}} = $t if ($t->{category} eq 'bitmask');
- $enums->{$t->{name}} = $t if ($t->{category} eq 'enum');
- }
+ my $f = openOutput($sys, $s->{name});
+ print $f formatFunctionPointer($vk, $api, $s);
+ closeOutput($sys, $s->{name}, $f);
}
-print Dumper($masks);
-foreach my $k (sort keys %{$masks}) {
- my $s = $masks->{$k};
- my $t;
-
- if ($s->{requires}) {
- $t = $vk->{data}->{$s->{requires}};
- } elsif ($s->{name} =~ m/(.*)Flags([0-9A-Z]*)/o && defined $vk->{data}->{"$1FlagBits$2"}) {
- print "> $s->{name} $1FlagBits$2\n";
- $t = $vk->{data}->{"$1FlagBits$2"};
- } else {
- print "? $s->{name}\n";
- $t = $s;
- }
- print "! $s->{name} r=$s->{requires}\n" if !defined($t);
- #print Dumper($t);
+exit 0;
-}
-}
+# ###################################################################### #
sub loadTypes {
my $api = shift;
foreach my $t (@{$config->{objects}}) {
if ($t->{type} eq 'type') {
my $nopts = $#{$t->{options}};
- my $type;
-
- if ($nopts >= 0 && defined($types->{$t->{options}->[0]})) {
- $type = { %{$types->{$t->{options}->[0]}} };
- } elsif ($#{$t->{items}} >= 0) {
- $type = {};
- } else {
- die ("No prototype provided/found for empty type ".Dumper($t));
- }
-
- if ($#{$t->{items}} >= 0) {
- foreach my $s (@{$t->{items}}) {
- my $x = {
- code => defined($s->{literal}) ? $s->{literal} : $s->{options}->[$#{$s->{options}}]
- };
+ my $type = {};
- $x->{eval} = 1 if config::optionFlag('eval', $s);
-
- $type->{$s->{match}} = $x;
- }
- }
+ die ("No prototype provided/found for empty type ".Dumper($t)) if ($#{$t->{items}} < 0 && $#{$t->{options}} < 0);
- # check other options
+ # Check options / load inherited values
foreach my $o (@{$t->{options}}) {
if ($o =~ m/^accessor=(.*)$/o) {
die "No template $1" if !defined($templates->{$1});
$type->{'need-alloc'} = 1;
} elsif ($o eq 'is-instance') {
$type->{'is-instance'} = 1;
+ } elsif (defined($types->{$o})) {
+ $type = { %$type, %{$types->{$o}} };
} else {
- # doesn't ignore implied parant type
- #die "Unknown option '$o' in ".Dumper($t);
+ die "Unknown option '$o' in ".Dumper($t);
}
}
+ # Load the fields
+ foreach my $s (@{$t->{items}}) {
+ # FIXME: maybe i don't want struct here, as with templates
+ my $x = {
+ code => defined($s->{literal}) ? $s->{literal} : $s->{options}->[$#{$s->{options}}]
+ };
+
+ $x->{eval} = 1 if config::optionFlag('eval', $s);
+
+ $type->{$s->{match}} = $x;
+ }
+
+ # Write to all aliases
foreach my $k (split /,/,$t->{name}) {
$types->{$k} = $type;
}
insert => {},
};
- foreach my $s (@{$t->{items}}) {
- $code->{$s->{match}} = $s->{literal};
- $code->{$s->{match}} =~ s/^\t//gm;
- }
foreach my $o (@{$t->{options}}) {
if ($o =~ m/insert=(.*)/) {
foreach my $t (split /,/,$1) {
$code->{insert}->{$2} = $templates->{$1}->{$2};
}
}
+ } elsif ($o =~ m/^fields=(.*)/) {
+ $code->{fields} = $1;
+ } else {
+ die ("Unknown option $o");
}
}
+ foreach my $s (@{$t->{items}}) {
+ $code->{$s->{match}} = $s->{literal};
+ $code->{$s->{match}} =~ s/^\t//gm;
+
+ # hack since the template is a string
+ $code->{"$s->{match}:eval"}->{eval} = 1 if config::optionFlag('eval', $s);
+ }
+
$templates->{$t->{name}} = $code;
} elsif ($t->{type} eq 'override') {
foreach my $s (@{$t->{items}}) {
# This doens't need to worry about overrides
- foreach my $m (@{$s->{items}}) {
- my $type = $types->{$m->{deref}};
- my $diff = $m->{bitOffset} - $offset;
+ if ($s->{category} eq 'struct') {
+ foreach my $m (@{$s->{items}}) {
+ my $type = $types->{$m->{deref}};
+ my $diff = $m->{bitOffset} - $offset;
- push @fields, "MemoryLayout.paddingLayout($diff)" if $diff;
+ push @fields, "MemoryLayout.paddingLayout($diff)" if $diff;
- if ($type) {
- my $v = buildVars($s, $m, $type);
+ if ($type) {
+ my $v = buildVars($s, $m, $type);
- push @fields, code::formatTemplate($v->{layout}, $v).".withName(\"$m->{name}\") /* $m->{deref} $m->{fullType} */";
- $offset = $m->{bitOffset} + $m->{bitSize};
- } else {
- push @fields, "/* Missing: $m->{deref} $m->{name} */";
+ push @fields, code::formatTemplate($v->{layout}, $v).".withName(\"$m->{name}\") /* $m->{deref} $m->{fullType} */";
+ $offset = $m->{bitOffset} + $m->{bitSize};
+ } else {
+ push @fields, "/* Missing: $m->{deref} $m->{name} */";
+ }
+ }
+ } else {
+ foreach my $m (@{$s->{items}}) {
+ my $type = $types->{$m->{deref}};
+
+ if ($type) {
+ my $v = buildVars($s, $m, $type);
+
+ push @fields, code::formatTemplate($v->{layout}, $v).".withName(\"$m->{name}\") /* $m->{deref} $m->{fullType} */";
+ $offset = ($m->{bitOffset} + $m->{bitSize}) if ($m->{bitOffset} + $m->{bitSize}) > $offset;
+ } else {
+ push @fields, "/* Missing: $m->{deref} $m->{name} */";
+ }
}
}
+
my $diff = $s->{bitSize} - $offset;
+
push @fields, "MemoryLayout.paddingLayout($diff)" if $diff;
return "MemoryLayout.".$s->{category}."Layout(\n\t\t".join(",\n\t\t", @fields).").withName(\"$s->{name}\")";
}
+sub formatAccessorIf {
+ my $s = shift;
+ my $m = shift;
+ my $info = shift;
+ my $type = shift;
+ my $field = shift;
+ my $v = shift;
+ my $accessor = $type->{accessor};
+ my $template = $accessor->{$field};
+
+ if ($template) {
+ $template = eval($template) if ($accessor->{"$field:eval"});
+
+ die "Error executing template $field $accessor->{$field}: $@" if (!defined($template));
+
+ push @{$info->{$field}}, code::formatTemplate($template, $v) if $template;
+ }
+}
+
sub formatStruct {
my $vk = shift;
my $api = shift;
my $override = $overrides->{$s->{name}};
my $template = $override->{template} ? $override->{template} : $templates->{'struct-writeonly'};
+ my @fields = split(/,/, $template->{fields});
+ my $info;
- my $info = {
- get => [],
- set => [],
- getorset => [],
- varhandle => [],
- init => [],
- create => {},
- };
+ map { $info->{$_} = [] } @fields;
- if ($s->{category} eq 'struct') {
- $info->{create}->{create} = {
- setallArgs => [ 'SegmentAllocator alloc$' ],
- setall => [],
- };
- } elsif ($s->{category} eq 'union') {
- foreach my $m (@{$s->{items}}) {
- $info->{create}->{"create$m->{Name}"} = {
- setallArgs => [ 'SegmentAllocator alloc$' ],
+ my $setall = defined $info->{'java-setall'};
+
+ if ($setall) {
+ if ($s->{category} eq 'struct') {
+ $info->{create}->{create} = {
+ 'setall-arg' => [ 'SegmentAllocator alloc$' ],
setall => [],
};
+ } elsif ($s->{category} eq 'union') {
+ foreach my $m (@{$s->{items}}) {
+ $info->{create}->{"create$m->{Name}"} = {
+ 'setall-arg' => [ 'SegmentAllocator alloc$' ],
+ setall => [],
+ };
+ }
+ } else {
+ die;
}
- } else {
- die;
}
#map { $_->{typeInfo} = buildVars($s, $_, $types->{$_->{deref}}) } @{$s->{items}};
my $nstar = $m->{deref} =~ tr/*/*/;
my $deref = defined($override->{$m->{name}}) && defined($override->{$m->{name}}->{type}) ? $override->{$m->{name}}->{type} : $m->{deref};
my $type = $types->{$deref};
- my $v = buildVars($s, $m, $type);
die "No type $deref ".Dumper($m, $s) if !$type;
- #push @{$info->{getset}}, map { "// $_" } split(/\n/, Dumper($m->{deref}, $type, $override->{$m->{name}}));
- push @{$info->{varhandle}}, "/* ? Accessor: $m->{fullType} [$m->{deref}] $m->{name} len=$m->{len} lenfor=$m->{lengthfor} override=$deref */";
-
if ($type->{accessor}) {
- push @{$info->{getorset}}, code::formatTemplate($type->{accessor}->{getorset}, $v) if $type->{accessor}->{getorset};
+ my $v = buildVars($s, $m, $type);
+ my @todump;
if ($m->{values}) {
- push @{$info->{init}}, code::formatTemplate($type->{accessor}->{init}, $v) if $type->{accessor}->{init};
- push @{$info->{get}}, code::formatTemplate($type->{accessor}->{get}, $v) if $type->{accessor}->{get};
+ @todump = qw(init initat set setat);
} else {
- push @{$info->{get}}, code::formatTemplate($type->{accessor}->{get}, $v) if $type->{accessor}->{get};
- push @{$info->{set}}, code::formatTemplate($type->{accessor}->{set}, $v) if $type->{accessor}->{set};
+ @todump = qw(get getat set setat getorset getorsetat);
# FIXME: something here is adding length parameters which are already handled by the setXX() calls
- if (!$m->{'no-setall'}) {
+ if ($setall && !$m->{'no-setall'}) {
my $create = $s->{category} eq 'struct' ? $info->{create}->{create} : $info->{create}->{"create$m->{Name}"};
- push @{$create->{setallArgs}}, code::formatTemplate($type->{accessor}->{'setall-arg'}, $v) if $type->{accessor}->{'setall-arg'};
- push @{$create->{setall}}, code::formatTemplate($type->{accessor}->{setall}, $v) if $type->{accessor}->{setall};
+ #push @{$create->{setallArgs}}, code::formatTemplate($type->{accessor}->{'setall-arg'}, $v) if $type->{accessor}->{'setall-arg'};
+ #push @{$create->{setall}}, code::formatTemplate($type->{accessor}->{setall}, $v) if $type->{accessor}->{setall};
+ formatAccessorIf($s, $m, $create, $type, 'setall-arg', $v);
+ formatAccessorIf($s, $m, $create, $type, 'setall', $v);
}
}
+
+ push @{$info->{handle}}, code::formatTemplate($v->{handle}, $v)." /* $m->{name} $m->{fullType} ($m->{deref}) */" if $info->{handle} && $v->{handle};
+ push @{$info->{handleat}}, code::formatTemplate($v->{handleat}, $v) if $info->{handleat} && $v->{handleat};
+
+ foreach my $field (@todump) {
+ push @{$info->{$field}}, code::formatTemplate($type->{accessor}->{$field}, $v) if $info->{$field} && $type->{accessor}->{$field};
+ }
}
- push @{$info->{varhandle}}, code::formatTemplate($v->{handle}, $v) if $v->{handle};
}
# create constructors
name => $s->{name},
Name => $s->{Name},
layout => formatStructLayout($types, $s),
- init => join ("\n", @{$info->{init}}),
- get => join ("\n", @{$info->{get}}),
- set => join ("\n", @{$info->{set}}),
- getorset => join ("\n", @{$info->{getorset}}),
- #'java-setall-arguments' => join (",", @{$info->{setallArgs}}),
- #'java-setall' => join ("\n", @{$info->{setall}}),
- varhandle => join ("\n", @{$info->{varhandle}}),
+ #init => join ("\n", @{$info->{init}}),
+ #get => join ("\n", @{$info->{get}}),
+ #set => join ("\n", @{$info->{set}}),
+ #getorset => join ("\n", @{$info->{getorset}}),
+ ##'java-setall-arguments' => join (",", @{$info->{setallArgs}}),
+ ##'java-setall' => join ("\n", @{$info->{setall}}),
+ #varhandle => join ("\n", @{$info->{varhandle}}),
};
+ foreach my $field (@fields) {
+ $v->{$field} = join("\n", @{$info->{$field}});
+ }
# build sub-components using the full $v
my @createAll = ();
my $t = $template->{insert}->{$k};
if ($k eq 'create-all') {
- foreach my $kk (keys %{$info->{create}}) {
- my $create = $info->{create}->{$kk};
-
- if ($#{$create->{setallArgs}} > 0) {
- my $v = {
- create => $kk,
- Name => $s->{Name},
- 'java-setall-arguments' => join (', ', @{$create->{setallArgs}}),
- 'java-setall' => join ("\n\t\t", @{$create->{setall}}),
- };
- push @createAll, code::formatTemplateStream($t, $v);
+ if ($setall) {
+ foreach my $kk (keys %{$info->{create}}) {
+ my $create = $info->{create}->{$kk};
+
+ if ($#{$create->{'setall-arg'}} > 0) {
+ my $v = {
+ create => $kk,
+ Name => $s->{Name},
+ 'java-setall-arguments' => join (', ', @{$create->{'setall-arg'}}),
+ 'java-setall' => join ("\n\t\t", @{$create->{setall}}),
+ };
+ push @createAll, code::formatTemplateStream($t, $v);
+ }
}
}
} else {
$v->{$k} = code::formatTemplate($t, $v);
}
}
- $v->{'create-all'} = join("\n", @createAll);
+ $v->{'create-all'} = join("\n", @createAll) if $setall;
+
+ #die Dumper($info) if $s->{name} eq 'VkMemoryOpaqueCaptureAddressAllocateInfo';
join("\n", map { '// '.$_ } split(/\n/,Dumper($s)))."\n".
code::formatTemplateStream($template->{class}, $v);
#return if !defined($override->{template});
#return if ($s->{name} ne 'vkCmdUpdateBuffer');
+ my @arrayFields = qw(java-arg invoke-arg native-init query-init query-arg native-arg trampoline-arg);
+ my @fixedFields = qw(java-result java-result-return java-result-assign);
+
+ map { $info->{$_} = [] } @arrayFields;
+
foreach my $m (@{$s->{items}}) {
my $deref = defined($override->{$m->{name}}) && defined($override->{$m->{name}}->{type}) ? $override->{$m->{name}}->{type} : $m->{deref};
my $type = $types->{$deref};
my $v = buildVars($s, $m, $type);
- #push @javaArgs, "/* $m->{name} $m->{deref} */ " if !$v->{'java-argument'};
+ foreach my $field (@arrayFields) {
+ if ($v->{$field}) {
+ push @{$info->{$field}}, code::formatTemplate($v->{$field}, $v);
+ } elsif ($field eq 'query-arg') {
+ push @{$info->{$field}}, code::formatTemplate($v->{'invoke-arg'}, $v);
+ }
+ }
+
+ foreach my $field (@fixedFields) {
+ $info->{$field} = code::formatTemplate($v->{$field}, $v) if ($v->{$field});
+ }
- push @javaArgs, "/* $m->{name} $m->{deref} */ ".code::formatTemplate($v->{'java-arg'}, $v) if ($v->{'java-arg'});
- push @invokeArgs, code::formatTemplate($v->{'invoke-arg'}, $v) if ($v->{'invoke-arg'});
+ if (0) {
+ push @javaArgs, "/* $m->{name} $m->{deref} */ ".code::formatTemplate($v->{'java-arg'}, $v) if ($v->{'java-arg'});
+ push @invokeArgs, code::formatTemplate($v->{'invoke-arg'}, $v) if ($v->{'invoke-arg'});
- push @nativeInit, code::formatTemplate($v->{'native-init'}, $v) if ($v->{'native-init'});
- push @queryInit, code::formatTemplate($v->{'query-init'}, $v) if ($v->{'query-init'});
+ push @nativeInit, code::formatTemplate($v->{'native-init'}, $v) if ($v->{'native-init'});
+ push @queryInit, code::formatTemplate($v->{'query-init'}, $v) if ($v->{'query-init'});
- if ($v->{'query-arg'}) {
- push @queryArgs, code::formatTemplate($v->{'query-arg'}, $v);
- } elsif ($v->{'invoke-arg'}) {
- push @queryArgs, code::formatTemplate($v->{'invoke-arg'}, $v);
- }
+ if ($v->{'query-arg'}) {
+ push @queryArgs, code::formatTemplate($v->{'query-arg'}, $v);
+ } elsif ($v->{'invoke-arg'}) {
+ push @queryArgs, code::formatTemplate($v->{'invoke-arg'}, $v);
+ }
- push @nativeArgs, code::formatTemplate($v->{'native-arg'}, $v) if ($v->{'native-arg'});
- push @trampArgs, code::formatTemplate($v->{'trampoline-arg'}, $v) if ($v->{'trampoline-arg'});
+ push @nativeArgs, code::formatTemplate($v->{'native-arg'}, $v) if ($v->{'native-arg'});
+ push @trampArgs, code::formatTemplate($v->{'trampoline-arg'}, $v) if ($v->{'trampoline-arg'});
- $info->{'java-result'} = code::formatTemplate($v->{'java-result'}, $v) if ($v->{'java-result'});
- $info->{'java-result-return'} = code::formatTemplate($v->{'java-result-return'}, $v) if ($v->{'java-result-return'});
- $info->{'java-result-assign'} = code::formatTemplate($v->{'java-result-assign'}, $v) if ($v->{'java-result-assign'});
+ $info->{'java-result'} = code::formatTemplate($v->{'java-result'}, $v) if ($v->{'java-result'});
+ $info->{'java-result-return'} = code::formatTemplate($v->{'java-result-return'}, $v) if ($v->{'java-result-return'});
+ $info->{'java-result-assign'} = code::formatTemplate($v->{'java-result-assign'}, $v) if ($v->{'java-result-assign'});
+ }
$needScope = 1 if $type->{'need-scope'};
$needFrame = 1 if $type->{'need-frame'};
}
$info->{'create-frame'} = '(Frame frame$ = Frame.frame())' if $needFrame;
- push @javaArgs, 'SegmentAllocator alloc$' if $needAlloc;
- push @javaArgs, 'ResourceScope scope$' if $needScope;
+ $info->{'trampoline-scope'} = '(ResourceScope scope$$ = ResourceScope.newConfinedScope())' if $trampScope;
- $info->{'java-arguments'} = join ",\n\t", @javaArgs;
- $info->{'native-init'} = join "\n\t", @nativeInit;
- $info->{'invoke-arguments'} = join ", ", @invokeArgs;
- $info->{'query-init'} = join "\n\t\t\t", @queryInit;
- $info->{'query-arguments'} = join ", ", @queryArgs;
+ push @{$info->{'java-arg'}}, 'SegmentAllocator alloc$' if $needAlloc;
+ push @{$info->{'java-arg'}}, 'ResourceScope scope$' if $needScope;
- $info->{'trampoline-scope'} = '(ResourceScope scope$$ = ResourceScope.newConfinedScope())' if $trampScope;
- $info->{'native-arguments'} = join ",\n\t", @nativeArgs;
- $info->{'trampoline-arguments'} = join ",\n\t", @trampArgs;
+ foreach my $field (@arrayFields) {
+ my $with = $field =~ m/-arg$/n ? ",\n\t" : "\n\t";
+ $info->{$field} = join $with, @{$info->{$field}};
+ }
+
+ if (0) {
+ $info->{'java-arguments'} = join ",\n\t", @javaArgs;
+ $info->{'native-init'} = join "\n\t", @nativeInit;
+ $info->{'invoke-arguments'} = join ", ", @invokeArgs;
+ $info->{'query-init'} = join "\n\t\t\t", @queryInit;
+ $info->{'query-arguments'} = join ", ", @queryArgs;
+
+ $info->{'native-arguments'} = join ",\n\t", @nativeArgs;
+ $info->{'trampoline-arguments'} = join ",\n\t", @trampArgs;
+ }
$info->{successcodes} = $s->{successcodes} ? $s->{successcodes} : '';
$info->{errorcodes} = $s->{errorcodes} ? $s->{errorcodes}: '';
{java-set};
}
}}
+ getat {{
+ public {type} get{Name}AtIndex(long i$) {
+ return {java-getat};
+ }
+ }}
+ setat {{
+ public void set{Name}AtIndex(long i$, {type} {name}) {
+ {java-setat};
+ }
+ }}
# FIXME: only handles single element arrays
init {{ {name}$VH.set(this.segment, VkConstants.{values}); }}
{java-seti};
}
}}
+
+ setall-arg eval {{
+ if ($m->{len1} <= 4) {
+ join ", ", map { '{typei} {name}$'.$_ } (0 .. $m->{len1}-1);
+ } else {
+ "{typei}[] {name} /* $m->{deref} $m->{len1} */";
+ }
+ }}
+ setall eval {{
+ if ($m->{len1} <= 4) {
+ join "\n\t", map { "self\$.set{Name}Element($_, {name}\$$_);" } (0 .. $m->{len1}-1);
+ } else {
+ <<END;
+ if ({name} != null) {
+ try {
+ ((MemorySegment){name}\$SH.invokeExact(self\$.segment)).copyFrom(MemorySegment.ofArray({name}));
+ } catch (Throwable t) {
+ System.err.println("Copy error: " + t.getLocalizedMessage());
+ }
+ }
+END
+ }
+ }}
}
code value-array2d {
{java-set};
}
}}
+ getat {{
+ /* {deref} */
+ public {type} get{Name}AtIndex(long i$) {
+ return {java-getat};
+ }
+ }}
+ setat {{
+ /* {deref} */
+ public void set{Name}AtIndex(long i$, {type} {name}, SegmentAllocator alloc$) {
+ {java-setat};
+ }
+ }}
setall-arg {{ {type} {name} }}
setall {{ self$.set{Name}({name}, alloc$); }}
}
}
public static HandleArray<{name}> createArray(long length, SegmentAllocator alloc) {
- return HandleArray.createArray(1, alloc, {name}::create);
+ return HandleArray.createArray(length, alloc, {name}::create);
}
public MemoryAddress address() {
// TODO: evaluate how scope fits here
public static HandleArray<{name}> createArray(long length, SegmentAllocator alloc, DispatchInstance dispatch, ResourceScope scope) {
- return HandleArray.createArray(1, alloc, (a, s) -> create(a, dispatch, s), scope);
+ return HandleArray.createArray(length, alloc, (a, s) -> create(a, dispatch, s), scope);
}
public static HandleArray<{name}> createArray(long length, SegmentAllocator alloc, VkInstance instance, ResourceScope scope) {
- return HandleArray.createArray(1, alloc, (a, s) -> create(a, instance.dispatch, s), scope);
+ return HandleArray.createArray(length, alloc, (a, s) -> create(a, instance.dispatch, s), scope);
}
public MemoryAddress address() {
}
# default - writeonly struct
-code struct-writeonly insert=struct:header,struct:create-all {
+code struct-writeonly insert=struct:header,struct:create-all
+ fields=init,set,getorset,handle,java-setall {
class {{
// template: struct-writeonly:class
package {package};
{set}
{getorset}
- {varhandle}
+ {handle}
}
}}
}
-code struct-writeonly-array insert=struct:header,struct:create-all,struct:array {
+code struct-writeonly-array insert=struct:header,struct:create-all,struct:array
+ fields=init,set,getorset,setat,getorsetat,handle,handleat,java-setall {
class {{
// template: struct-writeonly-array:class
package {package};
{set}
{getorset}
- {varhandle}
+ {setat}
+ {getorsetat}
+
+ {handle}
+ {handleat}
}
}}
}
-code struct-readonly insert=struct:header {
+code struct-readonly insert=struct:header
+ fields=init,get,getorset,handle {
class {{
// template: struct-readonly:class
package {package};
{get}
{getorset}
- {varhandle}
+ {handle}
}
}}
}
-code struct-readonly-array insert=struct:header,struct:array {
+code struct-readonly-array insert=struct:header,struct:array
+ fields=init,get,getorset,getat,getorsetat,handle,handleat {
class {{
// template: struct-readonly-array:class
package {package};
{get}
{getorset}
- {varhandle}
+ {getat}
+ {getorsetat}
+
+ {handle}
+ {handleat}
}
}}
}
-code struct-readwrite insert=struct:header,struct:create-all {
+code struct-readwrite insert=struct:header,struct:create-all
+ fields=init,get,set,getorset,handle,java-setall {
class {{
// template: struct-readwrite:class
package {package};
{set}
{getorset}
- {varhandle}
+ {handle}
}
}}
}
-code struct-readwrite-array insert=struct:header,struct:create-all,struct:array {
+code struct-readwrite-array insert=struct:header,struct:create-all,struct:array
+ fields=init,get,getat,set,setat,getorset,getorsetat,handle,handleat,java-setall {
class {{
// template: struct-readwrite-array:class
package {package};
{set}
{getorset}
- {varhandle}
+ {getat}
+ {setat}
+ {getorsetat}
+
+ {handle}
+ {handleat}
}
}}
}
# ###################################################################### #
-# how to arrays? in code?
-# how to lengths?
-
+# Basic value-based accessor
type value accessor=value {
- java-get {{ ({type}){name}$VH.get(this.segment) }}
- java-set {{ {name}$VH.set(this.segment, {name}) }}
- handle {{ final static VarHandle {name}$VH = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("{name}")); }}
+ native-value {{ {name} }}
+
+ native-get {{ ({type}){name}$VH.get(this.segment) }}
+ handle {{ final static VarHandle {name}$VH = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("{name}")); }}
+
+ java-get {{ {native-get} }}
+ java-set {{ {name}$VH.set(this.segment, {native-value}) }}
+
+ native-getat {{ ({type}){name}$AH.get(this.segment, i$) }}
+ native-setat {{ {name}$AH.set(this.segment, i$, {native-value}) }}
+ handleat {{ final static VarHandle {name}$AH = MemoryLayout.sequenceLayout(LAYOUT).varHandle(MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("{name}")); }}
+
+ java-getat {{ {native-getat} }}
+ java-setat {{ {native-setat} }}
}
type value-array accessor=value-array {
native-get {{ (MemorySegment){name}$SH.invokeExact(this.segment) }}
java-get {{ {type}.create({native-get}) }}
- java-geti {{ ({typei}){name}$EH.get(i$) }}
- java-seti {{ {name}$EH.set(i$, {name}) }}
+ java-geti {{ ({typei}){name}$EH.get(this.segment, i$) }}
+ java-seti {{ {name}$EH.set(this.segment, i$, {name}) }}
handle {{
final static MethodHandle {name}$SH = LAYOUT.sliceHandle(MemoryLayout.PathElement.groupElement("{name}"));
final static VarHandle {name}$EH = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("{name}"), MemoryLayout.PathElement.sequenceElement());
type value-array2d accessor=value-array2d {
native-get {{ (MemorySegment){name}$SH.invokeExact(this.segment) }}
java-get {{ {type}.create({native-get}) }}
- java-geti {{ ({typei}){name}$EH.get(i$, j$) }}
- java-seti {{ {name}$EH.set(i$, j$, {name}) }}
+ java-geti {{ ({typei}){name}$EH.get(this.segment, i$, j$) }}
+ java-seti {{ {name}$EH.set(this.segment, i$, j$, {name}) }}
handle {{
final static MethodHandle {name}$SH = LAYOUT.sliceHandle(MemoryLayout.PathElement.groupElement("{name}"));
final static VarHandle {name}$EH = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("{name}"), MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement());
# ###################################################################### #
# implied length types
type uint64_t-implied,size_t-implied uint64_t accessor=value-implied {
-
}
type uint32_t-implied uint32_t accessor=value-implied {
layout {{ Memory.POINTER }}
type {{ MemoryAddress }}
- native-get {{ (MemoryAddress){name}$VH.get(this.segment) }}
+ native-value {{ Memory.address({name}) }}
+ native-get {{ (MemoryAddress){name}$VH.get(this.segment) }}
- java-get {{ {native-get} }}
- java-set {{ {name}$VH.set(this.segment, Memory.address({name})) }}
+# java-get {{ {native-get} }}
+# java-set {{ {name}$VH.set(this.segment, Memory.address({name})) }}
}
type void* pointer;
type {{ String }}
java-get {{ ({native-get}).getUtf8String(0) }}
- java-set {{ {name}$VH.set(this.segment, alloc$.allocateUtf8String({name}).address()) }}
+ native-value {{ alloc$.allocateUtf8String({name}).address() }}
# this just verifies it's a string type
length eval {{
sub new {
my $class = shift;
+ my $sys = shift;
my $self = {
+ sys => $sys,
data => {},
extensions => [],
handles => {},
};
foreach my $feature (grep { $versions->{$_->{name}} } @{$vk->{features}}) {
- print "Feature $feature->{name}\n";
+ print "Feature $feature->{name}\n" if ($vk->{sys}->{verbose});
foreach my $req (@{$feature->{require}}) {
buildRequirement($vk, $data, $req);
}
} @{$vk->{extensions}}) {
foreach my $req (grep { (!defined($_->{feature})) || $versions->{$_->{feature}} }
@{$extension->{require}}) {
- print "Extension $extension->{name} $req->{feature}\n";
+ print "Extension $extension->{name} $req->{feature}\n" if ($vk->{sys}->{verbose});
buildRequirement($vk, $data, $req, $extension);
}
}
$s->{fullType} = 'VkFlags' if !defined $s->{fullType};
}
- if (0) {
- # Have to actually map the types too
- {
- my $del = {};
- my $add = {};
- foreach my $c (values %{$types}) {
- if ($c->{alias}) {
- print "T";
- while ($c->{alias}) {
- print " $c->{name}";
- $c = $vk->{data}->{$c->{alias}};
- }
- print " -> $c->{name}\n";
- }
- }
- map {delete $types->{$_} } (keys %$del);
- map {$data->{$_->{name}} = $_; $enums->{$_->{name}} = $_ } (values %$add);
- }
-
- # check type sare included?
- {
- my $del = {};
- my $add = {};
- foreach my $e (values %{$enums}) {
- if ($e->{alias}) {
- print "D";
- while ($e->{alias}) {
- print " $e->{name}";
- $del->{$e->{name}} = $e;
- $e = $vk->{data}->{$e->{alias}};
- }
- die if !defined($e);
- print " -> $e->{name}\n";
- $add->{$e->{name}} = $e;
- }
- }
- map {delete $enums->{$_} } (keys %$del);
- map {$data->{$_->{name}} = $_; $enums->{$_->{name}} = $_ } (values %$add);
- }
- }
-
my $api = {
data => $data,
handles => $handles,