From 10061a71f44a21be6140e3ddfa73df72cdf8592a Mon Sep 17 00:00:00 2001 From: Not Zed Date: Wed, 27 Apr 2022 14:55:51 +0930 Subject: [PATCH] Add upcall support for notzed.vulkan. Remove all VkAllocationCallbacks from calls to simplify api. --- .../classes/vulkan/test/TestMandelbrot.java | 59 +++--- src/notzed.vulkan/gen/command-types.api | 132 +++++++++++- src/notzed.vulkan/gen/gen.make | 1 + src/notzed.vulkan/gen/generate-vulkan | 189 ++++++++++++------ src/notzed.vulkan/gen/struct-types.api | 42 +--- src/notzed.vulkan/gen/vulkan.pm | 15 +- 6 files changed, 306 insertions(+), 132 deletions(-) diff --git a/src/notzed.vulkan.test/classes/vulkan/test/TestMandelbrot.java b/src/notzed.vulkan.test/classes/vulkan/test/TestMandelbrot.java index 4ebb002..0de2890 100755 --- a/src/notzed.vulkan.test/classes/vulkan/test/TestMandelbrot.java +++ b/src/notzed.vulkan.test/classes/vulkan/test/TestMandelbrot.java @@ -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 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 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 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(); } /** diff --git a/src/notzed.vulkan/gen/command-types.api b/src/notzed.vulkan/gen/command-types.api index 0bf03ce..309d6c5 100644 --- a/src/notzed.vulkan/gen/command-types.api +++ b/src/notzed.vulkan/gen/command-types.api @@ -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; } diff --git a/src/notzed.vulkan/gen/gen.make b/src/notzed.vulkan/gen/gen.make index 3e34cad..7d4ff14 100644 --- a/src/notzed.vulkan/gen/gen.make +++ b/src/notzed.vulkan/gen/gen.make @@ -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 \ diff --git a/src/notzed.vulkan/gen/generate-vulkan b/src/notzed.vulkan/gen/generate-vulkan index cb50afd..c3063a6 100755 --- a/src/notzed.vulkan/gen/generate-vulkan +++ b/src/notzed.vulkan/gen/generate-vulkan @@ -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); } diff --git a/src/notzed.vulkan/gen/struct-types.api b/src/notzed.vulkan/gen/struct-types.api index 1625945..1de0e54 100644 --- a/src/notzed.vulkan/gen/struct-types.api +++ b/src/notzed.vulkan/gen/struct-types.api @@ -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; diff --git a/src/notzed.vulkan/gen/vulkan.pm b/src/notzed.vulkan/gen/vulkan.pm index 4cc1e26..e3dfe13 100644 --- a/src/notzed.vulkan/gen/vulkan.pm +++ b/src/notzed.vulkan/gen/vulkan.pm @@ -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}; -- 2.39.5