1 module vulkanish.helpers.functions; 2 3 import std.traits; 4 static if (!is(typeof(Unconst))) 5 import core.internal.traits : Unconst; 6 7 import erupted; 8 import refedforeignptr; 9 10 import vulkanish.helpers.internal; 11 import vulkanish.helpers.error; 12 import vulkanish.helpers.types; 13 import vulkanish.helpers.enums; 14 15 import std.meta; 16 import std..string; 17 import std.conv; 18 import std.typecons; 19 20 alias vshEnumerateAlt(string name) = vshEnumerate!(functionMixin!("vk"~name)); 21 alias vshEnumerate(string name) = vshEnumerate!(functionMixin!("vkEnumerate"~name)); 22 template vshEnumerate(alias f_unenforced) 23 ////if (isCallable!f_unenforced) 24 { 25 static assert(isCallable!f_unenforced); 26 alias f = enforced!f_unenforced; 27 alias Params = Parameters!f; 28 PointerTarget!(Params[$-1])[] vshEnumerate(Params[0..$-2] args) { 29 uint count; 30 f(args, &count, null); 31 if (count == 0) 32 return []; 33 auto outArray = new PointerTarget!(Params[$-1])[count]; 34 f(args, &count, outArray.ptr); 35 return outArray; 36 } 37 } 38 39 40 alias vshCall(alias f) = vsh!f; 41 alias vsh(string name) = vsh!(functionMixin!("vk"~name)); 42 template vsh(alias f_unenforced) 43 ////if (isCallable!f_unenforced) 44 { 45 static assert(isCallable!f_unenforced); 46 alias f = enforced!f_unenforced; 47 alias Params = Parameters!f; 48 49 ////template hasAltType(T) { 50 //// static if (isPointer!T && is(Unconst!(PointerTarget!T) == struct)) 51 //// enum hasAltType = __traits(identifier, Unconst!(PointerTarget!T)).endsWith("CreateInfo"); 52 //// else 53 //// enum hasAltType = false; 54 ////} 55 ////template AltType(T) { 56 //// static if (hasAltType!T) 57 //// alias AltType = PointerTarget!T; 58 //// else 59 //// alias AltType = T; 60 ////} 61 ////template altArg(T)(T arg) { 62 //// 63 ////} 64 ////mixin forParams!Params; 65 ////static if (anySatisfy!(hasAltType,Params)) 66 //// mixin forParams!(staticMap!(AltType,Params)); 67 ////mixin template forParams(Params...) { 68 auto vsh(Params args) { 69 f(args); 70 } 71 // Second to last argument allocator. 72 static if (is(Params[$-2] == const(VkAllocationCallbacks)*)) { 73 // Given no allocator 74 auto vsh(Params[0..$-2] args, Params[$-1] lastArg) { 75 f(args,null,lastArg); 76 } 77 } 78 // Last argument allocator. 79 static if (is(Params[$-1] == const(VkAllocationCallbacks)*)) { 80 // Given no allocator 81 auto vsh(Params[0..$-1] args) { 82 f(args,null); 83 } 84 } 85 // Returning through last argument as pointer. 86 else static if (isPointer!(Params[$-1]) && __traits(compiles, {PointerTarget!(Params[$-1]) outPtr;})) { 87 // Given no out ptr. 88 auto vsh(Params[0..$-1] args) { 89 PointerTarget!(Params[$-1]) outPtr; 90 f(args,&outPtr); 91 return outPtr; 92 } 93 // Second to last argument allocator. 94 static if (is(Params[$-2] == const(VkAllocationCallbacks)*)) { 95 // Given no allocator nor out ptr. 96 auto vsh(Params[0..$-2] args) { 97 PointerTarget!(Params[$-1]) outPtr; 98 f(args,null,&outPtr); 99 return outPtr; 100 } 101 } 102 } 103 ////} 104 } 105 106 template vshDestroy(Ts...) if (Ts.length>0 && isHandleType!(Ts[$-1])) { 107 enum name = handleName!(Ts[$-1]); 108 alias f = functionMixin!("vkDestroy"~name); 109 110 auto vshDestroy(Ts args, const(VkAllocationCallbacks)* allocator) { 111 f(args,allocator); 112 } 113 auto vshDestroy(Ts args) { 114 f(args,null); 115 } 116 } 117 template vshDestroyRange(Ts...) if (Ts.length>0 && isHandleType!(ForeachType!(Ts[$-1]))) { 118 enum name = handleName!(ForeachType!(Ts[$-1])); 119 alias f = functionMixin!("vkDestroy"~name); 120 import std.algorithm; 121 122 auto vshDestroyRange(Ts args, const(VkAllocationCallbacks)* allocator) { 123 args[$-1].each!(h=>f(args[0..$-1],h,allocator)); 124 } 125 auto vshDestroyRange(Ts args) { 126 args[$-1].each!(h=>f(args[0..$-1],h,null)); 127 } 128 } 129 template vshFrees(Ts...) if (Ts.length>0 && isHandleType!(ForeachType!(Ts[$-1]))) { 130 enum name = handleName!(ForeachType!(Ts[$-1])); 131 alias f = functionMixin!("vkFree"~name~"s"); 132 133 auto vshFrees(Ts args) { 134 f(args[0..$-1], cast(uint) args[$-1].length, args[$-1].ptr); 135 } 136 } 137 138 template vshCreate(Ts...) if (Ts.length>0 && isCreateInfoType!(Ts[$-1])) { 139 enum name = createInfoName!(Ts[$-1]); 140 static if (is(typeof(functionMixin!("vkCreate"~name~"s")))) 141 alias f_unenforced = functionMixin!("vkCreate"~name~"s"); 142 else 143 alias f_unenforced = functionMixin!("vkCreate"~name); 144 alias f = enforced!f_unenforced; 145 alias Params = Parameters!f; 146 147 ////auto vshCreate(Ts args, const(VkAllocationCallbacks)* allocator, Params[$-1]* outPtr) { 148 //// f(args, allocator, outPtr); 149 ////} 150 ////// Second to last argument allocator. 151 ////static if (is(Params[$-2] == const(VkAllocationCallbacks)*)) { 152 //// // Given no allocator 153 //// auto vshCreate(Ts args, Vsh!(createInfoName!(Ts[$-1]))* outPtr) { 154 //// f(args,null,outPtr); 155 //// } 156 ////} 157 ////// Last argument allocator. 158 ////static if (is(Params[$-1] == const(VkAllocationCallbacks)*)) { 159 //// // Given no allocator 160 //// auto vsh(Ts args) { 161 //// f(args,null); 162 //// } 163 ////} 164 // Returning through last argument as pointer. 165 //// static if (isPointer!(Params[$-1]) && __traits(compiles, {PointerTarget!(Params[$-1]) outPtr;})) { 166 // Given no out ptr. 167 auto vshCreate(Ts args, const(VkAllocationCallbacks)* allocator) { 168 PointerTarget!(Params[$-1]) outPtr; 169 f(args, allocator, &outPtr); 170 return outPtr; 171 } 172 // Second to last argument allocator. 173 ////static if (is(Params[$-2] == const(VkAllocationCallbacks)*)) { 174 // Given no allocator nor out ptr. 175 auto vshCreate(Ts args) { 176 PointerTarget!(Params[$-1]) outPtr; 177 f(args,null,&outPtr); 178 return outPtr; 179 } 180 ////} 181 ////} 182 } 183 184 template vshCreateScoped(Ts...) 185 ////if ((Ts.length==1 && is(typeof(Ts[0])==string)) || (Ts.length==2 && isCallable!(Ts[0]) && isCallable!(Ts[1]))) 186 { 187 static if (Ts.length==1 && is(typeof(Ts[0])==string)) { 188 enum name = Ts[0]; 189 alias f_unenforced = functionMixin!("vkCreate"~Ts[0]); 190 import std.algorithm; 191 import std.uni; 192 alias destroy = destroyer!(Ts[0]); 193 ///static if (!is(typeof(functionMixin!("vkDestroy"~Ts[0]))) && is(typeof(functionMixin!("vkDestroy"~Ts[0][1..$].find!isUpper)))) 194 /// alias destroy = functionMixin!("vkDestroy"~Ts[0][1..$].find!isUpper); 195 ///static if (!is(typeof(functionMixin!("vkDestroy"~Ts[0]))) && is(typeof(functionMixin!("vkDestroy"~Ts[0][1..$].find!isUpper[0..$-1])))) 196 /// alias destroy = functionMixin!("vkDestroy"~Ts[0][1..$].find!isUpper[0..$-1]); 197 ///else 198 /// alias destroy = functionMixin!("vkDestroy"~Ts[0]); 199 } 200 else static if (Ts.length==1) { 201 alias f_unenforced = Ts[0]; 202 alias destroy = destroyer!(T[0]); 203 } 204 else static if (Ts.length==2 && isCallable!(Ts[0]) && isCallable!(Ts[1])) { 205 alias f_unenforced = Ts[0]; 206 alias destroy = Ts[1]; 207 } 208 else { 209 static assert(false); 210 } 211 alias f = enforced!f_unenforced; 212 alias Params = Parameters!f; 213 alias T = PointerTarget!(Params[$-1]); 214 alias ScopedT = VshScoped!T; 215 // Returns through last argument as pointer. 216 static assert (isPointer!(Params[$-1])); 217 ScopedT vshCreateScoped(Parameters!f[0..$-1] args) { 218 T outPtr; 219 f(args, &outPtr); 220 return ScopedT(args[0..Parameters!(ScopedT.__ctor).length-1], outPtr); 221 } 222 // Second to last argument allocator. 223 static assert (is(Params[$-2] == const(VkAllocationCallbacks)*)); 224 ScopedT vshCreateScoped(Params[0..$-2] args) { 225 T outPtr; 226 f(args, null, &outPtr); 227 return ScopedT(args[0..Parameters!(ScopedT.__ctor).length-1], outPtr); 228 } 229 } 230 231 string vshScopedDestroy(string v, string args="") { 232 if (args.strip!="") 233 args ~= ','; 234 return "scope (exit) if ("~v~" != null) { 235 import vulkanish.helpers.functions; 236 vshDestroy("~args~v~"); 237 ////import vulkanish.helpers.internal:destroyer; 238 ////import vulkanish.helpers.functions:vsh; 239 ////vsh!(destroyer!(typeof("~v~")))("~args~v~"); 240 }"; 241 } 242 string vshScopedDestroyRange(string v, string args="") { 243 if (args.strip!="") 244 args ~= ','; 245 return "scope (exit) { 246 import vulkanish.helpers.functions; 247 vshDestroyRange("~args~v~"); 248 ////import vulkanish.helpers.internal:destroyer; 249 ////import vulkanish.helpers.functions:vsh; 250 ////import std.algorithm:each; 251 ////"~v~".each!(h=>vshDestroy("~args~"h)); 252 ////"~v~".each!(h=>vsh!(destroyer!(typeof(h)))("~args~"h)); 253 }"; 254 } 255 string vshScopedFrees(string v, string args="") { 256 if (args.strip!="") 257 args ~= ','; 258 return "scope (exit) if ("~v~" != []) { 259 import vulkanish.helpers.functions; 260 vshFrees("~args~v~"); 261 }"; 262 } 263 264 265 266 267