Add upcall support for notzed.vulkan.
authorNot Zed <notzed@gmail.com>
Wed, 27 Apr 2022 05:25:51 +0000 (14:55 +0930)
committerNot Zed <notzed@gmail.com>
Wed, 27 Apr 2022 05:25:51 +0000 (14:55 +0930)
Remove all VkAllocationCallbacks from calls to simplify api.

src/notzed.vulkan.test/classes/vulkan/test/TestMandelbrot.java
src/notzed.vulkan/gen/command-types.api
src/notzed.vulkan/gen/gen.make
src/notzed.vulkan/gen/generate-vulkan
src/notzed.vulkan/gen/struct-types.api
src/notzed.vulkan/gen/vulkan.pm

index 4ebb002..0de2890 100755 (executable)
@@ -105,26 +105,25 @@ public class TestMandelbrot {
        void init_debug() throws Exception {
                if (!debug)
                        return;
-               /*
                try (Frame frame = Frame.frame()) {
-                       var cb = PFN_vkDebugUtilsMessengerCallbackEXT.upcall((severity, flags, data, dummy) -> {
+                       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_VERBOSE_BIT_EXT |
                                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,
+                               VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
+                               | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
+                               | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
                                cb,
                                null);
 
-                       logger = instance.vkCreateDebugUtilsMessengerEXT(info, null, scope);
+                       logger = instance.vkCreateDebugUtilsMessengerEXT(info, scope);
                }
-               */
-               //typedef VkBool32 (*PFN_vkDebugUtilsMessengerCallbackEXT)(VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *, void *);
-
        }
 
        void init_instance() throws Exception {
@@ -136,7 +135,7 @@ public class TestMandelbrot {
                                debug ? new String[] { "VK_EXT_debug_utils" } : null
                                );
 
-                       instance = VkInstance.vkCreateInstance(info, null, scope);
+                       instance = VkInstance.vkCreateInstance(info, scope);
                }
        }
 
@@ -194,7 +193,7 @@ public class TestMandelbrot {
                                null,
                                null);
 
-                       device = physicalDevice.vkCreateDevice(devinfo, null, scope);
+                       device = physicalDevice.vkCreateDevice(devinfo, scope);
 
                        System.out.printf("device = %s\n", device.address());
 
@@ -223,7 +222,7 @@ public class TestMandelbrot {
                                VK_SHARING_MODE_EXCLUSIVE,
                                null);
 
-                       VkBuffer buffer = device.vkCreateBuffer(buf_info, null, scope);
+                       VkBuffer buffer = device.vkCreateBuffer(buf_info, scope);
 
                        device.vkGetBufferMemoryRequirements(buffer, req);
 
@@ -231,7 +230,7 @@ public class TestMandelbrot {
                                req.getSize(),
                                find_memory_type(deviceMemoryProperties, req.getMemoryTypeBits(), properties));
 
-                       VkDeviceMemory memory = device.vkAllocateMemory(alloc, null, scope);
+                       VkDeviceMemory memory = device.vkAllocateMemory(alloc, scope);
 
                        device.vkBindBufferMemory(buffer, memory, 0);
 
@@ -261,7 +260,7 @@ public class TestMandelbrot {
                                0,
                                layout_binding);
 
-                       descriptorSetLayout = device.vkCreateDescriptorSetLayout(descriptor_layout, null, scope);
+                       descriptorSetLayout = device.vkCreateDescriptorSetLayout(descriptor_layout, scope);
 
                        /* Create descriptor pool */
                        VkDescriptorPoolSize type_count = VkDescriptorPoolSize.create(frame,
@@ -273,7 +272,7 @@ public class TestMandelbrot {
                                1,
                                type_count);
 
-                       descriptorPool = device.vkCreateDescriptorPool(descriptor_pool, null, scope);
+                       descriptorPool = device.vkCreateDescriptorPool(descriptor_pool, scope);
 
                        /* Allocate from pool */
                        HandleArray<VkDescriptorSetLayout> layout_table = VkDescriptorSetLayout.createArray(1, frame);
@@ -319,7 +318,7 @@ public class TestMandelbrot {
                                mandelbrot_cs.length() * 4,
                                mandelbrot_cs);
 
-                       mandelbrotShader = device.vkCreateShaderModule(vsInfo, null, scope);
+                       mandelbrotShader = device.vkCreateShaderModule(vsInfo, scope);
 
                        /* Link shader to layout */
                        HandleArray<VkDescriptorSetLayout> layout_table = VkDescriptorSetLayout.createArray(1, frame);
@@ -331,7 +330,7 @@ public class TestMandelbrot {
                                layout_table,
                                null);
 
-                       pipelineLayout = device.vkCreatePipelineLayout(pipelineinfo, null, scope);
+                       pipelineLayout = device.vkCreatePipelineLayout(pipelineinfo, scope);
 
                        /* Create pipeline */
                        VkComputePipelineCreateInfo pipeline = VkComputePipelineCreateInfo.create(frame,
@@ -346,7 +345,7 @@ public class TestMandelbrot {
                        stage.setModule(mandelbrotShader);
                        stage.setName(mandelbrot_entry, frame);
 
-                       device.vkCreateComputePipelines(null, pipeline, null, computePipeline);
+                       device.vkCreateComputePipelines(null, pipeline, computePipeline);
                }
        }
 
@@ -359,7 +358,7 @@ public class TestMandelbrot {
                                0,
                                computeQueueIndex);
 
-                       commandPool = device.vkCreateCommandPool(poolinfo, null, scope);
+                       commandPool = device.vkCreateCommandPool(poolinfo, scope);
 
                        VkCommandBufferAllocateInfo cmdinfo = VkCommandBufferAllocateInfo.create(frame,
                                commandPool,
@@ -406,7 +405,7 @@ public class TestMandelbrot {
 
                        // maybe this should take a HandleArray<Fence> rather than being a constructor
                        // FIXME: some local scope
-                       fence = device.vkCreateFence(fenceInfo, null, scope);
+                       fence = device.vkCreateFence(fenceInfo, scope);
                        fences.set(0, fence);
 
                        /* Await completion */
@@ -418,26 +417,26 @@ public class TestMandelbrot {
                                res = device.vkWaitForFences(fences, VK_TRUE, 1000000);
                        } while (res == VK_TIMEOUT);
 
-                       device.vkDestroyFence(fence, null);
+                       device.vkDestroyFence(fence);
                }
        }
 
        void shutdown() {
-               device.vkDestroyCommandPool(commandPool, null);
-               device.vkDestroyPipeline(computePipeline.getAtIndex(0), null);
-               device.vkDestroyPipelineLayout(pipelineLayout, null);
-               device.vkDestroyShaderModule(mandelbrotShader, null);
+               device.vkDestroyCommandPool(commandPool);
+               device.vkDestroyPipeline(computePipeline.getAtIndex(0));
+               device.vkDestroyPipelineLayout(pipelineLayout);
+               device.vkDestroyShaderModule(mandelbrotShader);
 
-               device.vkDestroyDescriptorPool(descriptorPool, null);
-               device.vkDestroyDescriptorSetLayout(descriptorSetLayout, null);
+               device.vkDestroyDescriptorPool(descriptorPool);
+               device.vkDestroyDescriptorSetLayout(descriptorSetLayout);
 
-               device.vkFreeMemory(dst.memory(), null);
-               device.vkDestroyBuffer(dst.buffer(), null);
+               device.vkFreeMemory(dst.memory());
+               device.vkDestroyBuffer(dst.buffer());
 
-               device.vkDestroyDevice(null);
+               device.vkDestroyDevice();
                if (logger != null)
-                       instance.vkDestroyDebugUtilsMessengerEXT(logger, null);
-               instance.vkDestroyInstance(null);
+                       instance.vkDestroyDebugUtilsMessengerEXT(logger);
+               instance.vkDestroyInstance();
        }
 
        /**
index 0bf03ce..309d6c5 100644 (file)
@@ -122,53 +122,125 @@ code method-extension-query {
   }}
 }
 
+# ###################################################################### #
+
+# common parts for funcpointer
+code funcpointer {
+  common {{
+       public {java-result} call({java-arguments});
+
+       public final static FunctionDescriptor DESCRIPTOR =
+               {function-descriptor};
+  }}
+  upcall {{
+       public static FunctionPointer<{rename}> upcall({rename} target$, ResourceScope scope$) {
+               interface Trampoline {
+                       {native-result} call({native-arguments});
+               }
+               Trampoline trampoline = ({native-arguments}) -> {
+                       // frame?  scope?
+                       try {trampoline-scope} {
+                               {trampoline-result-define}
+                               {trampoline-result-assign}target$.call({trampoline-arguments});
+                               {trampoline-result-return}
+                       } catch (Throwable t) {
+                               throw new RuntimeException(t);
+                       }
+               };
+               return new FunctionPointer<>(
+                       Memory.upcall(
+                               MethodHandles.lookup(),
+                               trampoline,
+                               "call",
+                               "{trampoline-signature}",
+                               DESCRIPTOR,
+                               scope$),
+                       target$);
+       }
+  }}
+  # vulkan has none
+  downcall {{ }}
+}
+
+code funcpointer-readwrite insert=funcpointer:common,funcpointer:upcall,funcpointer:downcall {
+  class {{
+       package {package};
+
+       import jdk.incubator.foreign.*;
+       import java.lang.invoke.*;
+       import au.notzed.nativez.*;
+
+       @FunctionalInterface
+       public interface {name} {
+
+               {common}
+
+               {upcall}
+               {downcall}
+       }
+  }}
+}
+
+# ###################################################################### #
+
 type value {
        java-arg        {{ {type} {name} }}
-       native-arg      {{ {carrier} {name}$ }}
-
        invoke-arg      {{ {name} }}
+
+       native-arg      {{ {carrier} {name}$ }}
+       trampoline-arg  {{ {name}$ }}
 }
 
 type value-array {
        java-arg        {{ {type} {name} }}
-       native-arg      {{ {carrier} {name}$ }}
-
        invoke-arg      {{ {name} }}
+
+       native-arg      {{ {carrier} {name}$ }}
+       trampoline-arg  {{ {name}$ }}
 }
 
 type value-array2d {
        java-arg        {{ {type} {name} }}
-       native-arg      {{ {carrier} {name}$ }}
-
        invoke-arg      {{ {name} }}
+
+       native-arg      {{ {carrier} {name}$ }}
+       trampoline-arg  {{ {name}$ }}
 }
 
 type uint8_t,char value {
+       carrier {{ byte }}
        type    {{ byte }}
        layout  {{ Memory.BYTE }}
 }
 
 type uint16_t value {
+       carrier {{ short }}
        type    {{ short }}
        layout  {{ Memory.SHORT }}
 }
 
 type uint32_t,int,int32_t value {
+       carrier {{ int }}
        type    {{ int }}
        layout  {{ Memory.INT }}
+       sig             {{ I }}
 }
 
 type uint64_t,int64_t,size_t value {
+       carrier {{ long }}
        type    {{ long }}
        layout  {{ Memory.LONG }}
+       sig             {{ J }}
 }
 
 type float value {
+       carrier {{ float }}
        type    {{ float }}
        layout  {{ Memory.FLOAT }}
 }
 
 type double value {
+       carrier {{ double }}
        type    {{ double }}
        layout  {{ Memory.DOUBLE }}
 }
@@ -227,12 +299,20 @@ type uint32_t-length uint32_t {
 # select=len?  or what?
 
 type pointer value {
+       carrier {{ MemoryAddress }}
        layout  {{ Memory.POINTER }}
        type    {{ MemoryAddress }}
+       sig             {{ Ljdk/incubator/foreign/MemoryAddress; }}
 
        invoke-arg      {{ Memory.address({name}) }}
 }
 
+type void {
+       type            {{ void }}
+       sig                     {{ V }}
+       java-arg        {{ }}
+}
+
 type void* pointer;
 
 type funcpointer pointer {
@@ -303,12 +383,14 @@ type char* pointer need-frame {
 
        invoke-arg      {{ (Addressable)frame$.allocateUtf8String({name}) }}
 
+       trampoline-arg  {{ {name}$.getUtf8String(0) }}
+
        # this just verifies it's a string type
        length eval     {{
                if ($v->{len} =~ m/null-terminated/) {
                        1;
                } else {
-                       die Dumper($v, $s);
+                       print "Warning: not sure if this is a string: $s->{name} $m->{name}\n";
                }
        }}
 
@@ -369,8 +451,10 @@ type struct inline {
        layout  {{ {baseType}.LAYOUT }}
 }
 
-type struct* pointer {
+type struct* pointer trampoline-scope {
        type            {{ {baseType} }}
+
+       trampoline-arg  {{ {baseType}.create({name}$, scope$$) }}
 }
 
 type struct*-length pointer-length {
@@ -407,6 +491,19 @@ type instance handle is-instance {
        native-arg      {{ }}
 }
 
+# A pointer type which is always ignored/supressed, e.g. VkAllocationCallbacks *
+type struct*-ignore,void*-ignore void* {
+       java-arg        {{ }}
+       invoke-arg      {{ (Addressable)MemoryAddress.NULL }}
+       trampoline-arg  {{ }}
+}
+
+type void*-return void* {
+       native-result-define    {{ MemoryAddress result$; }}
+       native-result-assign    {{ result$ = (MemoryAddress) }}
+       java-result-return              {{ return result$; }}
+}
+
 type funcpointer-return funcpointer need-scope {
        native-result-define    {{ MemoryAddress result$; }}
        native-result-assign    {{ result$ = (MemoryAddress) }}
@@ -417,6 +514,10 @@ type uint32_t-return uint32_t {
        native-result-define    {{ int result$; }}
        native-result-assign    {{ result$ = (int) }}
        java-result-return              {{ return result$; /* uint32_t */ }}
+
+       trampoline-result-define        {{ int result$$; }}
+       trampoline-result-assign        {{ result$$ = (int) }}
+       trampoline-result-return        {{ return result$$; /* uint32_t */ }}
 }
 
 type uint64_t-return,size_t-return uint64_t {
@@ -559,4 +660,19 @@ override commands {
        vkAllocateDescriptorSets device=type:instance pDescriptorSets=type:VkDescriptorSet-alloc;
 
        vkMapMemory device=type:instance ppData=type:vkMapMemory-output;
+
+       # Don't need userData
+       PFN_vkDebugUtilsMessengerCallbackEXT pUserData=type:void*-ignore;
+       PFN_vkDebugReportCallbackEXT pUserData=type:void*-ignore;
+       PFN_vkDeviceMemoryReportCallbackEXT pUserData=type:void*-ignore;
+
+       # Mapped to a NativeSymbol via 'funcpointer' type
+       PFN_vkVoidFunction ignore;
+
+       # Don't need VkAllocationCallbacks, don't need these
+       PFN_vkAllocationFunction ignore;
+       PFN_vkReallocationFunction ignore;
+       PFN_vkFreeFunction ignore;
+       PFN_vkInternalAllocationNotification ignore;
+       PFN_vkInternalFreeNotification ignore;
 }
index 3e34cad..7d4ff14 100644 (file)
@@ -3,6 +3,7 @@ bin/status/notzed.vulkan.classes: \
        bin/status/notzed.vulkan.export
 
 bin/status/notzed.vulkan.export: \
+       $(NATIVEZ_HOME)/lib/notzed.nativez.jar \
        src/notzed.vulkan/gen/generate-vulkan \
        src/notzed.vulkan/gen/vulkan.pm \
        src/notzed.vulkan/gen/struct-types.api \
index cb50afd..c3063a6 100755 (executable)
@@ -186,8 +186,14 @@ foreach my $s (values %{$api->{commands}}) {
                }
        }
 
-       # implied lengths
+       # other per-item things
        foreach my $m (@{$s->{items}}) {
+               my $so = $structTypes->{overrides}->{$m->{baseType}};
+
+               if ($so->{ignore}) {
+                       $m->{deref} .= '-ignore';
+               }
+
                if ($m->{lengthfor}) {
                        my $nstar = $m->{deref} =~ tr/*/*/;
                        if ($nstar == 0) {
@@ -259,7 +265,8 @@ if (1) {
                print $f Dumper({
                        'handles' => $api->{handles},
                                'types' => $api->{types},
-                               'commands' => $api->{commands}
+                               'commands' => $api->{commands},
+                               'funcpointers' => $api->{funcpointers},
                                                });
                close $f;
        }
@@ -322,6 +329,10 @@ if (1) {
                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);
@@ -344,6 +355,10 @@ if (1) {
                die if !defined $s;
                next if $s->{alias};
 
+               my $override = $commandTypes->{overrides}->{$s->{name}};
+
+               next if $override->{ignore};
+
                my $f = openOutput($sys, $s->{name});
                print $f formatFunctionPointer($vk, $api, $s);
                closeOutput($sys, $s->{name}, $f);
@@ -472,6 +487,8 @@ sub loadTypes {
                                        $type->{'need-frame'} = 1;
                                } elsif ($o eq 'need-scope') {
                                        $type->{'need-scope'} = 1;
+                               } elsif ($o eq 'trampoline-scope') {
+                                       $type->{'trampoline-scope'} = 1;
                                } elsif ($o eq 'need-alloc') {
                                        $type->{'need-alloc'} = 1;
                                } elsif ($o eq 'is-instance') {
@@ -516,12 +533,11 @@ sub loadTypes {
                                        } elsif ($o =~ m/^(.*)=accessor:(.*)/) {
                                                die "No accessor template $o" if !defined($templates->{$2});
                                                $c->{$1}->{accessor} = $templates->{$2};
-                                       #} elsif ($o =~ m/^(.*)=method:(.*)/) {
-                                       #       die "No method template $o" if !defined($templates->{$2});
-                                       #       $c->{$1}->{method} = $templates->{$2};
                                        } elsif ($o =~ m/^template=(.*)/) {
                                                die "No template $o" if !defined($templates->{$1});
                                                $c->{template} = $templates->{$1};
+                                       } elsif ($o eq 'ignore') {
+                                               $c->{ignore} = 1;
                                        }
                                }
                                $overrides->{$s->{match}} = $c;
@@ -785,6 +801,7 @@ sub analyseFields {
                $seen->{$m->{fullType}} = $type.$array;
                $m->{deref} = $type.$array;
 
+               # Calculate name, with some fixup hacks
                my $name = $m->{name};
                #if ($s->{type} =~ m/struct|union/on)
                {
@@ -1074,63 +1091,28 @@ sub formatHandle {
        code::formatTemplateStream($template->{class}, $v);
 }
 
-sub formatFunctionPointer {
-       my $vk = shift;
-       my $api = shift;
-       my $s = shift;
-       my $templates = $structTypes->{templates};
-       my $template = $templates->{funcpointer}->{class};
-
-       my $info = {
-               init => [],
-       };
-
-       my $vcall = {
-               package => 'vulkan',
-               name => $s->{name},
-               Name => $s->{Name},
-       };
-
-       my $v = {
-               package => 'vulkan',
-               name => $s->{name},
-               Name => $s->{Name},
-               init => join ("\n", @{$info->{init}}),
-               upcall => code::formatTemplateStream($templates->{funcpointer}->{upcall}, $vcall),
-               downcall => code::formatTemplateStream($templates->{funcpointer}->{downcall}, $vcall),
-       };
-
-       code::formatTemplateStream($template, $v);
-}
-
-sub formatFunctionDescriptor {
-       my $ct = shift;
+sub formatSignature {
        my $s = shift;
+       my $types = $commandTypes->{types};
+       my $d = '(';
 
-       my $templates = $ct->{templates};
-       my $types = $ct->{types};
-       my $overrides = $ct->{overrides};
-
-       my @fields = ();
-       my $void = $s->{proto}->{fullType} eq 'void';
-       my $override = $overrides->{$s->{name}};
-
-       foreach my $m ($void ? () : $s->{proto}, @{$s->{items}}) {
-               my $deref = defined($override->{$m->{name}}) && defined($override->{$m->{name}}->{type}) ? $override->{$m->{name}}->{type} : $m->{deref};
-               my $type = $types->{$deref};
-
-               die "No type found ".Dumper($m, $s, $override) if !$type;
+       foreach my $m (@{$s->{items}}) {
+               my $x = $types->{$m->{deref}};
 
-               my $v = buildVars($s, $m, $type);
+               die "No sig defined ".Dumper($m) if !defined($x) || !defined($x->{sig});
 
-               push @fields, code::formatTemplate($v->{layout}, $v)." /* $m->{deref} $m->{name} */";
+               $d .= $x->{sig}->{code};
        }
+       $d .= ')';
 
-       return ($void ? 'FunctionDescriptor.ofVoid(' : 'FunctionDescriptor.of(')
-               .join(",\n\t\t", @fields).')';
+       my $m = $s->{proto};
+       my $x = $types->{$m->{deref}};
+       die "No sig defined ".Dumper($m) if !defined($x) || !defined($x->{sig});
+       $d .= $x->{sig}->{code};
 }
 
-sub formatFunction {
+# TODO: only collect shit we need
+sub collectFunctionInfo {
        my $api = shift;
        my $ct = shift;
        my $s = shift;
@@ -1139,7 +1121,6 @@ sub formatFunction {
        my $overrides = $ct->{overrides};
        my $void = $s->{proto}->{fullType} eq 'void';
        my $override = $overrides->{$s->{name}};
-       my $template = $override->{template} ? $override->{template} : $templates->{method};
 
        my @javaArgs = ();
        my @invokeArgs = ();
@@ -1147,24 +1128,34 @@ sub formatFunction {
        my @queryInit = ();
        my @queryArgs = ();
 
+       my @nativeArgs = ();
+       my @trampArgs = ();
+
        my $info = {
                rename => $s->{name},
                name => $s->{name},
                'function-descriptor' => formatFunctionDescriptor($ct, $s),
                'native-result-define' => '',
                'native-result-assign' => '',
+               'native-result' => 'void',
+               'trampoline-result-define' => '',
+               'trampoline-result-assign' => '',
+               'trampoline-scope' => '',
                'result-test' => '',
                'create-frame' => '',
                'java-result' => 'void',
                'java-result-assign' => '',
-               'java-result-return' => 'return;',
                'result-throw' => '',
+
+               'java-result-return' => 'return;',
+               'trampoline-result-return' => 'return;',
        };
 
        my $hasInstance = 0;
        my $needFrame = 0;
        my $needAlloc = 0;
        my $needScope = 0;
+       my $trampScope = 0;
 
        #return if !defined($override->{template});
        #return if ($s->{name} ne 'vkCmdUpdateBuffer');
@@ -1191,6 +1182,9 @@ sub formatFunction {
                        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'});
+
                $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'});
@@ -1199,6 +1193,7 @@ sub formatFunction {
                $needFrame = 1 if $type->{'need-frame'};
                $needAlloc = 1 if $type->{'need-alloc'};
                $hasInstance = 1 if $type->{'is-instance'};
+               $trampScope = 1 if $type->{'trampoline-scope'};
        }
 
        $info->{'static'} = $hasInstance ? '' : 'static ';
@@ -1220,17 +1215,22 @@ sub formatFunction {
                my $m = $s->{proto};
                my $type = defined($override->{$m->{name}}) ? $override->{$m->{name}}->{type} : $types->{$m->{deref}.'-return'};
 
-               die Dumper($m, $s) if !defined($type);
+               die "No type '$m->{deref}-return' ".Dumper($m, $s) if !defined($type);
                die Dumper($m, $s) if !defined($type->{'java-result-return'});
 
                my $v = buildVars($s, $m, $type);
 
                $info->{'native-result-define'} = code::formatTemplate($v->{'native-result-define'}, $v);
                $info->{'native-result-assign'} = code::formatTemplate($v->{'native-result-assign'}, $v);
-               $info->{'native-result-define'}.= join("", map { "// $_\n" } split(/\n/, Dumper($m)));
+               #$info->{'native-result-define'}.= join("", map { "// $_\n" } split(/\n/, Dumper($m)));
                $info->{'java-result'} = code::formatTemplate($v->{type}, $v);
                $info->{'java-result-return'} = code::formatTemplate($v->{'java-result-return'}, $v);
 
+               $info->{'native-result'} = code::formatTemplate($v->{'carrier'}, $v);
+               $info->{'trampoline-result-define'} = code::formatTemplate($v->{'trampoline-result-define'}, $v);
+               $info->{'trampoline-result-assign'} = code::formatTemplate($v->{'trampoline-result-assign'}, $v);
+               $info->{'trampoline-result-return'} = code::formatTemplate($v->{'trampoline-result-return'}, $v);
+
                $needScope = 1 if $type->{'need-scope'};
        }
 
@@ -1244,9 +1244,82 @@ sub formatFunction {
        $info->{'query-init'} = join "\n\t\t\t", @queryInit;
        $info->{'query-arguments'} = join ", ", @queryArgs;
 
+       $info->{'trampoline-scope'} = '(ResourceScope scope$$ = ResourceScope.newConfinedScope())' if $trampScope;
+       $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}: '';
 
+       if ($s->{category} eq 'funcpointer') {
+               $info->{'trampoline-signature'} = formatSignature($s);
+       }
+
+       $info;
+}
+
+sub formatFunctionPointer {
+       my $vk = shift;
+       my $api = shift;
+       my $s = shift;
+       my $template = $commandTypes->{templates}->{'funcpointer-readwrite'};
+       my $info = collectFunctionInfo($api, $commandTypes, $s);
+
+       my $v = {
+               package => 'vulkan',
+               name => $s->{name},
+               Name => $s->{Name},
+       };
+
+       foreach my $k (keys %{$template->{insert}}) {
+               my $t = $template->{insert}->{$k};
+
+               $v->{$k} = code::formatTemplate($t, $info);
+       }
+
+       code::formatTemplateStream($template->{class}, $v);
+}
+
+sub formatFunctionDescriptor {
+       my $ct = shift;
+       my $s = shift;
+
+       my $templates = $ct->{templates};
+       my $types = $ct->{types};
+       my $overrides = $ct->{overrides};
+
+       my @fields = ();
+       my $void = $s->{proto}->{fullType} eq 'void';
+       my $override = $overrides->{$s->{name}};
+
+       foreach my $m ($void ? () : $s->{proto}, @{$s->{items}}) {
+               my $deref = defined($override->{$m->{name}}) && defined($override->{$m->{name}}->{type}) ? $override->{$m->{name}}->{type} : $m->{deref};
+               my $type = $types->{$deref};
+
+               die "No type found ".Dumper($m, $s, $override) if !$type;
+
+               my $v = buildVars($s, $m, $type);
+
+               push @fields, code::formatTemplate($v->{layout}, $v)." /* $m->{deref} $m->{name} */";
+       }
+
+       return ($void ? 'FunctionDescriptor.ofVoid(' : 'FunctionDescriptor.of(')
+               .join(",\n\t\t", @fields).')';
+}
+
+sub formatFunction {
+       my $api = shift;
+       my $ct = shift;
+       my $s = shift;
+       my $templates = $ct->{templates};
+       my $types = $ct->{types};
+       my $overrides = $ct->{overrides};
+       my $void = $s->{proto}->{fullType} eq 'void';
+       my $override = $overrides->{$s->{name}};
+       my $template = $override->{template} ? $override->{template} : $templates->{method};
+
+       my $info = collectFunctionInfo($api, $ct, $s);
+
        #join("\n", map { '// '.$_ } split(/\n/,Dumper($s)))."\n".
        code::formatTemplate($template->{invoke}, $info);
 }
index 1625945..1de0e54 100644 (file)
@@ -2,6 +2,8 @@
 
 # types for structs and unions
 
+# ###################################################################### #
+
 #accessor=code template
 # {type} - java type
 # {java-get}
@@ -258,33 +260,7 @@ code handle-dispatch {
   }}
 }
 
-# FIXME: unimplemented
-code funcpointer {
-  class {{
-       package {package};
-       import jdk.incubator.foreign.*;
-       import java.lang.invoke.*;
-       import au.notzed.nativez.*;
-
-       public interface {name} {
-
-               void call();
-
-               {upcall}
-               {downcall}
-       }
-  }}
-  upcall {{
-       public static FunctionPointer<{Name}> upcall({Name} target$, ResourceScope scope$) {
-               throw new UnsupportedOperationException();
-       }
-  }}
-  downcall {{
-       public static FunctionPointer<{Name}> downcall(MemoryAddress target$, ResourceScope scope$) {
-               throw new UnsupportedOperationException();
-       }
-  }}
-}
+# ###################################################################### #
 
 # shared struct components
 code struct {
@@ -500,6 +476,8 @@ code struct-readwrite-array insert=struct:header,struct:create-all,struct:array
   }}
 }
 
+# ###################################################################### #
+
 # how to arrays?  in code?
 # how to lengths?
 
@@ -804,12 +782,14 @@ override structs {
        VkCommandBuffer         template=handle-dispatch;
        VkQueue                         template=handle-dispatch;
 
+       VkAllocationCallbacks   ignore;
+
        #VkQueueFamilyProperties        template=struct-readwrite;
 
-       # TODO: fill these in, there's a good number of them
-       #VkPhysicalDeviceMemoryProperties template=struct-readonly;
-       #VkMemoryRequirements template=struct-readonly;
-       #VkPipelineExecutableInternalRepresentationKHR template=struct-readonly;
+       # Override default read/write
+       VkDebugUtilsMessengerCallbackDataEXT template=struct-readonly;
+       VkDebugUtilsLabelEXT template=struct-readonly-array;
+       VkDebugUtilsObjectNameInfoEXT template=struct-readonly-array;
 
        # override default array-length behaviours, some of these are independent of the array pointer
        VkAccelerationStructureBuildGeometryInfoKHR geometryCount=type:uint32_t;
index 4cc1e26..e3dfe13 100644 (file)
@@ -707,15 +707,20 @@ sub analyseFunctionPointer {
                $s->{proto} = makeParameter('result$', $rt);
                $s->{items} = [];
 
-               foreach my $a (@args) {
-                       my ($fullType, $name) = $a =~ m/^(.*)\s+(\S+)$/o;
-
-                       push @{$s->{items}}, makeParameter($name, $fullType);
+               if ($#args != 0 || $args[0] ne 'void') {
+                       foreach my $a (@args) {
+                               if (my ($fullType, $name) = $a =~ m/^(.*)\s+(\S+)$/o) {
+                                       push @{$s->{items}}, makeParameter($name, $fullType);
+                               } else {
+                                       die "Unable to parse function pointer argument '$a'\n";
+                               }
+                       }
                }
        } else {
-               die Dumper($s);
+               die "Unable to parse function pointer prototype '$s->{fullType}'\n";
        }
        $s->{Name} = $s->{name};
+
        delete $s->{type};
        delete $s->{baseType};
        delete $s->{fullType};