1# Copyright 2018 Google LLC 2# SPDX-License-Identifier: MIT 3 4from .common.codegen import CodeGen 5from .common.vulkantypes import \ 6 VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator 7 8from .wrapperdefs import VulkanWrapperGenerator 9from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE 10 11class HandleMapCodegen(VulkanTypeIterator): 12 def __init__(self, cgen, inputVar, handlemapVarName, prefix, isHandleFunc): 13 self.cgen = cgen 14 self.inputVar = inputVar 15 self.prefix = prefix 16 self.handlemapVarName = handlemapVarName 17 18 def makeAccess(varName, asPtr = True): 19 return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr) 20 21 def makeLengthAccess(varName): 22 return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName) 23 24 def makeLengthAccessGuard(varName): 25 return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName) 26 27 self.exprAccessor = makeAccess(self.inputVar) 28 self.exprAccessorValue = makeAccess(self.inputVar, asPtr = False) 29 self.lenAccessor = makeLengthAccess(self.inputVar) 30 self.lenAccessorGuard = makeLengthAccessGuard(self.inputVar) 31 32 self.checked = False 33 self.isHandleFunc = isHandleFunc 34 35 def needSkip(self, vulkanType): 36 return False 37 38 def makeCastExpr(self, vulkanType): 39 return "(%s)" % ( 40 self.cgen.makeCTypeDecl(vulkanType, useParamName=False)) 41 42 def asNonConstCast(self, access, vulkanType): 43 if vulkanType.staticArrExpr: 44 casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access) 45 elif vulkanType.accessibleAsPointer(): 46 casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access) 47 else: 48 casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access) 49 return casted 50 51 def onCheck(self, vulkanType): 52 pass 53 54 def endCheck(self, vulkanType): 55 pass 56 57 def onCompoundType(self, vulkanType): 58 59 if self.needSkip(vulkanType): 60 self.cgen.line("// TODO: Unsupported : %s" % 61 self.cgen.makeCTypeDecl(vulkanType)) 62 return 63 access = self.exprAccessor(vulkanType) 64 lenAccess = self.lenAccessor(vulkanType) 65 lenAccessGuard = self.lenAccessorGuard(vulkanType) 66 67 isPtr = vulkanType.pointerIndirectionLevels > 0 68 69 if lenAccessGuard is not None: 70 self.cgen.beginIf(lenAccessGuard) 71 72 if isPtr: 73 self.cgen.beginIf(access) 74 75 if lenAccess is not None: 76 77 loopVar = "i" 78 access = "%s + %s" % (access, loopVar) 79 forInit = "uint32_t %s = 0" % loopVar 80 forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess) 81 forIncr = "++%s" % loopVar 82 83 self.cgen.beginFor(forInit, forCond, forIncr) 84 85 accessCasted = self.asNonConstCast(access, vulkanType) 86 self.cgen.funcCall(None, self.prefix + vulkanType.typeName, 87 [self.handlemapVarName, accessCasted]) 88 89 if lenAccess is not None: 90 self.cgen.endFor() 91 92 if isPtr: 93 self.cgen.endIf() 94 95 if lenAccessGuard is not None: 96 self.cgen.endIf() 97 98 def onString(self, vulkanType): 99 pass 100 101 def onStringArray(self, vulkanType): 102 pass 103 104 def onStaticArr(self, vulkanType): 105 if not self.isHandleFunc(vulkanType): 106 return 107 108 accessLhs = self.exprAccessor(vulkanType) 109 lenAccess = self.lenAccessor(vulkanType) 110 111 self.cgen.stmt("%s->mapHandles_%s(%s%s, %s)" % \ 112 (self.handlemapVarName, vulkanType.typeName, 113 self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), 114 accessLhs, lenAccess)) 115 116 def onStructExtension(self, vulkanType): 117 access = self.exprAccessor(vulkanType) 118 119 castedAccessExpr = "(%s)(%s)" % ("void*", access) 120 self.cgen.beginIf(access) 121 self.cgen.funcCall(None, self.prefix + "extension_struct", 122 [self.handlemapVarName, castedAccessExpr]) 123 self.cgen.endIf() 124 125 def onPointer(self, vulkanType): 126 if self.needSkip(vulkanType): 127 return 128 129 if not self.isHandleFunc(vulkanType): 130 return 131 132 access = self.exprAccessor(vulkanType) 133 lenAccess = self.lenAccessor(vulkanType) 134 lenAccess = "1" if lenAccess is None else lenAccess 135 136 self.cgen.beginIf(access) 137 138 self.cgen.stmt( \ 139 "%s->mapHandles_%s(%s%s, %s)" % \ 140 (self.handlemapVarName, 141 vulkanType.typeName, 142 self.makeCastExpr(vulkanType.getForNonConstAccess()), 143 access, 144 lenAccess)) 145 146 self.cgen.endIf() 147 148 def onValue(self, vulkanType): 149 if not self.isHandleFunc(vulkanType): 150 return 151 access = self.exprAccessor(vulkanType) 152 self.cgen.stmt( 153 "%s->mapHandles_%s(%s%s)" % \ 154 (self.handlemapVarName, vulkanType.typeName, 155 self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), 156 access)) 157 158class VulkanHandleMap(VulkanWrapperGenerator): 159 def __init__(self, module, typeInfo): 160 VulkanWrapperGenerator.__init__(self, module, typeInfo) 161 162 self.codegen = CodeGen() 163 164 self.handlemapPrefix = "handlemap_" 165 self.toMapVar = "toMap" 166 self.handlemapVarName = "handlemap" 167 self.handlemapParam = \ 168 makeVulkanTypeSimple(False, "VulkanHandleMapping", 1, 169 self.handlemapVarName) 170 self.voidType = makeVulkanTypeSimple(False, "void", 0) 171 172 self.handlemapCodegen = \ 173 HandleMapCodegen( 174 None, 175 self.toMapVar, 176 self.handlemapVarName, 177 self.handlemapPrefix, 178 lambda vtype : typeInfo.isHandleType(vtype.typeName)) 179 180 self.knownDefs = {} 181 182 self.extensionHandlemapPrototype = \ 183 VulkanAPI(self.handlemapPrefix + "extension_struct", 184 self.voidType, 185 [self.handlemapParam, STRUCT_EXTENSION_PARAM_FOR_WRITE]) 186 187 def onBegin(self,): 188 VulkanWrapperGenerator.onBegin(self) 189 self.module.appendImpl(self.codegen.makeFuncDecl( 190 self.extensionHandlemapPrototype)) 191 192 def onGenType(self, typeXml, name, alias): 193 VulkanWrapperGenerator.onGenType(self, typeXml, name, alias) 194 195 if name in self.knownDefs: 196 return 197 198 category = self.typeInfo.categoryOf(name) 199 200 if category in ["struct", "union"] and alias: 201 self.module.appendHeader( 202 self.codegen.makeFuncAlias(self.handlemapPrefix + name, 203 self.handlemapPrefix + alias)) 204 205 if category in ["struct", "union"] and not alias: 206 207 structInfo = self.typeInfo.structs[name] 208 209 typeFromName = \ 210 lambda varname: \ 211 makeVulkanTypeSimple(varname == "from", name, 1, varname) 212 213 handlemapParams = \ 214 [self.handlemapParam] + \ 215 list(map(typeFromName, [self.toMapVar])) 216 217 handlemapPrototype = \ 218 VulkanAPI(self.handlemapPrefix + name, 219 self.voidType, 220 handlemapParams) 221 222 def funcDefGenerator(cgen): 223 self.handlemapCodegen.cgen = cgen 224 for p in handlemapParams: 225 cgen.stmt("(void)%s" % p.paramName) 226 for member in structInfo.members: 227 iterateVulkanType(self.typeInfo, member, 228 self.handlemapCodegen) 229 230 self.module.appendHeader( 231 self.codegen.makeFuncDecl(handlemapPrototype)) 232 self.module.appendImpl( 233 self.codegen.makeFuncImpl(handlemapPrototype, funcDefGenerator)) 234 235 def onGenCmd(self, cmdinfo, name, alias): 236 VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias) 237 238 def onEnd(self,): 239 VulkanWrapperGenerator.onEnd(self) 240 241 def forEachExtensionHandlemap(ext, castedAccess, cgen): 242 cgen.funcCall(None, self.handlemapPrefix + ext.name, 243 [self.handlemapVarName, castedAccess]) 244 245 self.module.appendImpl( 246 self.codegen.makeFuncImpl( 247 self.extensionHandlemapPrototype, 248 lambda cgen: self.emitForEachStructExtension( 249 cgen, 250 self.voidType, 251 STRUCT_EXTENSION_PARAM_FOR_WRITE, 252 forEachExtensionHandlemap))) 253