Some work on the header version of vulkan binding.
[panamaz] / src / notzed.vkheader / gen / vkheader.api
1 # -*- Mode:text; tab-width:4; electric-indent-mode: nil; indent-line-function:insert-tab; -*-
2
3 # FIXME: struct init for an array of struct needs to set the sType fields if appropriate
4 # FIXME: extension function pointers resolved and stored per-object, should just be stored on the vkinstance or something
5
6 # these are for the set-all constructors
7
8 # TODO: the set String and String[] things should be the same,
9 #  either use the segment scope to allocate or take the segment as an argument
10 #  probably the former
11
12 # **char, i.e. char *array[]
13 type /^u64:u64:i8$/ copy=<pointer>
14 # select=vkstring template=code:getset-frame
15 {
16         length          {{ 'get'.($m->{'array-size'}->{rename}).'()' }}
17         type            {{ 'String[]' }}
18         tojava          {{ 'Memory.toStringArray({value}, {length})' }}
19 #       tonative        {{ 'frame$.copy({value})' }}
20         tonative        {{ 'Frame.copy({segment}, {value}).address()' }}
21         typei           {{ 'String' }}
22 }
23
24 # *char, i.e. string
25 type /^u64:(?<ctype>i8)$/ copy=<pointer> {
26         type            {{ 'String' }}
27         tonative        {{ '(Addressable)({value} != null ? frame$.copy({value}) : MemoryAddress.NULL)' }}
28
29         setnative       {{ '{name}$VH.set({segment}, Frame.copy({segment}, {value}).address())' }}
30 #       copynative      {{ 'SegmentAllocator.nativeAllocator({segment}.scope()).allocateUtf8String({value})' }}
31 #       copynative      {{ '((SegmentAllocator){segment}).allocateUtf8String({value})' }}
32 #       copynative      {{ 'frame$.copy({value})' }}
33
34         tojava          {{ '({value}).getUtf8String(0L)' }}
35 }
36
37 # 1d array of primitive
38 type /^\[(?<length>\d+)(?<ctype>[uif]\d+)\]$/ select=vkarray
39                 copy=<pointer> template=code:getbyvalue,code:getsetelement {
40         layout          {{ "MemoryLayout.sequenceLayout({length}, {layouti})" }}
41 #       type            {{ ucfirst($typeSizes{$match->{ctype}})."Array" }}
42         type            {{ $typeSizes{$match->{ctype}}."[]" }}
43         tojava          {{ "{type}.createArray({value}, $match->{length}, {scope})" }}
44         tonative        {{ "(Addressable)Memory.address({value})" }}
45         lea                     {{ "(MemorySegment)$m->{name}\$SH.invokeExact({segment})" }}
46         getnative       {{ "({lea}).toArray({layouti})" }}
47         setnative       {{ '({lea}).copyFrom(MemorySegment.ofArray({value}))' }}
48         varhandle       {{
49                 "final static MethodHandle $m->{name}\$SH = LAYOUT.sliceHandle(MemoryLayout.PathElement.groupElement(\"$m->{name}\"));\n".
50                 "final static VarHandle $m->{name}\$EH = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement(\"$m->{name}\"), MemoryLayout.PathElement.sequenceElement());\n"
51         }}
52
53         typei           {{ "$typeSizes{$match->{ctype}}" }}
54         layouti         {{ 'Memory.'.uc($typeSizes{$match->{ctype}}) }}
55         getnativei      {{ "({typei})$m->{name}\$EH.get({segment}, {index})" }}
56         setnativei      {{ "$m->{name}\$EH.set({segment}, {index}, ({typei}){value})" }}
57 }
58
59 # 2d array of primitive
60 type /^\[(?<length0>\d+)\[(?<length1>\d+)(?<ctype>[uif]\d+)\]\]$/ select=vkarray
61                 copy=<pointer> template=code:getbyvalue,code:getsetelement2d {
62         layout          {{ "MemoryLayout.sequenceLayout({length0}, MemoryLayout.sequenceLayout({length1}, Memory.".uc($typeSizes{$match->{ctype}})."))" }}
63 #       type            {{ ucfirst($typeSizes{$match->{ctype}})."Array" }}
64         type            {{ $typeSizes{$match->{ctype}}."[]" }}
65         tojava          {{ "{type}.create({value})" }}
66         tonative        {{ "(Addressable)Memory.address({value})" }}
67
68         lea                     {{ "(MemorySegment)$m->{name}\$SH.invokeExact({segment})" }}
69         getnative       {{ "({lea}).toArray({layouti})" }}
70         setnative       {{ '({lea}).copyFrom(MemorySegment.ofArray({value}))' }}
71
72         typei           {{ "$typeSizes{$match->{ctype}}" }}
73         layouti         {{ 'Memory.'.uc($typeSizes{$match->{ctype}}) }}
74         getnativei      {{ "({typei})$m->{name}\$EH.get({segment}, {index0}, {index1})" }}
75         setnativei      {{ "$m->{name}\$EH.set({segment}, {index0}, {index1}, ({typei}){value})" }}
76
77         varhandle       {{
78                 "final static MethodHandle $m->{name}\$SH = LAYOUT.sliceHandle(MemoryLayout.PathElement.groupElement(\"$m->{name}\"));\n".
79                 "final static VarHandle $m->{name}\$EH = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement(\"$m->{name}\"), MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.sequenceElement());\n"
80         }}
81 }
82
83 # this passes instance to the create functions
84 type /^u64:u64:\$\{(\w+)\}$/ select=vkinstance copy=<pointer> {
85         length          {{ $m->{'array-size'} ? 'get'.($m->{'array-size'}->{rename}).'()' : 'Long.MAX_VALUE' }}
86         type            {{ !$m->{array} ? 'PointerArray' : 'HandleArray<{typei}>' }}
87         tojava          {{
88                 !$m->{array}
89                 ? 'PointerArray.createArray({value}, {length}, {scope})'
90                 : 'HandleArray.createArray({value}, {length}, (a, s) -> {typei}.create(instance, a, s), {scope})'
91         }}
92         # tojavai ... ?
93         carrieri        {{ "MemoryAddress" }}
94         typei           {{ "$data->{$m->{type}}->{rename}" }}
95         tojavai         {{ "{typei}.create(instance, {value}, {scope})" }}
96 }
97
98 %include types.api;
99 %include code.api;
100
101 %require vkheader.pm;
102
103 %stage.postprocess vkheader::postprocess;
104
105 # extern package ... types
106 extern xlib {
107         struct:_XDisplay rename=XDisplay;
108 }
109
110 # field rename function
111 #   field:remname=func:[function]
112 #     [function] is a defined function that will take:
113 #     function(name, member, struct)
114
115 # TODO: make rename func and <matcher> syntax the same
116 #  perhaps field:rename=<invoke=vkheader::renameField>
117 #          func:<invoke=vkheader::matchObjectFunction>
118
119 struct <default> rename=s/_T$// field:rename=func:vkheader::renameField access=rw default=all {
120 }
121
122 struct VkInstance_T {
123   # override this otherwise it wants to return PFN_vkVoidFunction
124   func:vkGetInstanceProcAddr {{
125         static final MethodHandle vkGetInstanceProcAddr$FH = Memory.downcall("vkGetInstanceProcAddr", FunctionDescriptor.of(Memory.POINTER, Memory.POINTER, Memory.POINTER));
126         public NativeSymbol vkGetInstanceProcAddr(String pName) {
127                 MemoryAddress result$;
128                 try (Frame frame$ = Frame.frame()) {
129                         result$ = (MemoryAddress)vkGetInstanceProcAddr$FH.invokeExact((jdk.incubator.foreign.Addressable)address(), (Addressable)(pName != null ? frame$.copy(pName) : MemoryAddress.NULL));
130                         return NativeSymbol.ofAddress(pName, result$, scope());
131                 } catch (Throwable t) {
132                         throw new RuntimeException(t);
133                 }
134         }
135   }}
136 #       func:<invoke=vkheader::matchCreateFunction>;
137         func:vkCreateInstance;
138         func:<invoke=vkheader::matchObjectFunction>;
139
140   # a few helpers
141   code:<inline> {{
142         public HandleArray<VkPhysicalDevice> vkEnumeratePhysicalDevices(SegmentAllocator alloc, ResourceScope scope) {
143                 try (Frame frame = Frame.frame()) {
144                         IntArray count = IntArray.createArray(1, frame);
145                         vkEnumeratePhysicalDevices(count, null);
146                         var list = VkPhysicalDevice.createArray(this, count.get(0), alloc, scope);
147                         vkEnumeratePhysicalDevices(count, list);
148                         return list;
149                 }
150         }
151   }}
152 }
153
154 struct VkDevice_T {
155 #       func:<invoke=vkheader::matchCreateFunction>;
156         func:<invoke=vkheader::matchObjectFunction>;
157
158   code:<inline> {{
159         public MemorySegment vkMapMemory(VkDeviceMemory memory, long offset, long size, int flags, ResourceScope scope$) {
160                 try (Frame frame = Frame.frame()) {
161                         PointerArray result = PointerArray.createArray(1, frame);
162
163                         vkMapMemory(memory, offset, size, flags, result);
164
165                         // possibly can make this readonly etc based on flags
166                         return MemorySegment.ofAddress(result.getAtIndex(0), size, scope$);
167                 }
168         }
169   }}
170
171 }
172
173 struct VkPhysicalDevice_T {
174 #       func:<invoke=vkheader::matchCreateFunction>;
175         func:<invoke=vkheader::matchObjectFunction>;
176
177   code:<inline> {{
178         public VkQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties(SegmentAllocator alloc) {
179                 try (Frame frame = Frame.frame()) {
180                         IntArray count = IntArray.createArray(1, frame);
181                         vkGetPhysicalDeviceQueueFamilyProperties(count, null);
182                         VkQueueFamilyProperties props = VkQueueFamilyProperties.createArray(count.getAtIndex(0), alloc);
183                         vkGetPhysicalDeviceQueueFamilyProperties(count, props);
184                         return props;
185                 }
186         }
187   }}
188 }
189
190 struct /Vk/ {
191 #       func:<invoke=vkheader::matchCreateFunction>;
192         func:<invoke=vkheader::matchObjectFunction>;
193 }
194
195 call <default> access=rw {
196 }
197
198 call PFN_vkDebugUtilsMessengerCallbackEXT access=w {
199 }
200
201 call PFN_vkGetDeviceProcAddr access=r {
202 }
203
204 #call /PFN_vk/ access=rw {
205 #}
206
207 func vkCreateInstance {
208         result$ success=VK_SUCCESS,1;
209         pInstance return;
210 }
211
212 library VkConstants {
213         define:api-constants;           # this is generated by vkheader.pm.init
214         define:extensions;
215         enum://;
216 }
217
218 enum // {
219 }
220
221 define extensions vkheader.h {
222         /^VK_.*_(SPEC_VERSION|EXTENSION_NAME)$/ include;
223 }
224
225 code vulkan {
226
227   create-all {{
228         public static {java-result} create{rename}(Frame frame$, {java-arguments}) {
229                 try {
230                         {java-result} self$ = {java-result}.create(frame$);
231                         {set-init}
232                         {set-all}
233                         return self$;
234                 } catch (Throwable t) {
235                         throw new RuntimeException(t);
236                 }
237         }
238   }}
239
240   invoke-dynamic-init-instance {{ {name}$NS = vkGetInstanceProcAddr("{name}"); }}
241   invoke-dynamic-init {{ {name}$NS = instance.vkGetInstanceProcAddr("{name}"); }}
242
243   invoke-dynamic {{
244         final NativeSymbol {name}$NS;
245         final static MethodHandle {name}$DH = Memory.downcall({function-descriptor});
246         public {java-result} {rename}({java-arguments}) {
247                 {native-output-define}
248                 {native-result-define}
249                 try {create-frame}{
250                         {native-output-init}
251                         {native-result-assign}{name}$DH.invokeExact({name}$NS, {native-call});
252                         {native-output-copy}
253                         {result-test}{
254                                 {java-result-assign}
255                                 {on-success}
256                                 {java-result-return}
257                         }
258                 } catch (Throwable t) {
259                         throw new RuntimeException(t);
260                 }
261                 {result-throw}
262         }
263   }}
264
265   handle-dynamic {{
266 package {package};
267 import jdk.incubator.foreign.*;
268 import java.lang.invoke.*;
269 import au.notzed.nativez.*;
270
271 public class {rename} implements Pointer {
272
273         MemoryAddress address;
274         ResourceScope scope;
275         VkInstance instance;
276
277         private {rename}(VkInstance instance, MemoryAddress address, ResourceScope scope) {
278                 this.address = address;
279                 this.scope = scope;
280                 this.instance = instance;
281                 {init}
282         }
283
284         public static {rename} create(VkInstance instance, MemoryAddress address, ResourceScope scope) {
285                 return MemoryAddress.NULL != address ? new {rename}(instance, address, scope) : null;
286         }
287
288         public static HandleArray<{rename}> createArray(VkInstance instance, long count, SegmentAllocator alloc, ResourceScope scope) {
289                 return HandleArray.createArray(count, alloc, (a, s)-> create(instance, a, s), scope);
290         }
291
292         @Override
293         public MemoryAddress address() {
294                 return address;
295         }
296
297         @Override
298         public ResourceScope scope() {
299                 return scope;
300         }
301
302         {defines}
303         {enums}
304         {methods}
305 }
306 }}
307 }