1# Copyright 2018 Google LLC 2# SPDX-License-Identifier: MIT 3 4from .common.codegen import CodeGen, VulkanWrapperGenerator, VulkanAPIWrapper 5from .common.vulkantypes import \ 6 VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, DISPATCHABLE_HANDLE_TYPES, NON_DISPATCHABLE_HANDLE_TYPES 7 8from .transform import TransformCodegen, genTransformsForVulkanType 9 10from .wrapperdefs import API_PREFIX_MARSHAL 11from .wrapperdefs import API_PREFIX_UNMARSHAL 12from .wrapperdefs import VULKAN_STREAM_TYPE 13 14from copy import copy 15from dataclasses import dataclass 16 17decoder_snapshot_decl_preamble = """ 18 19namespace android { 20namespace base { 21class BumpPool; 22class Stream; 23} // namespace base { 24} // namespace android { 25 26class VkDecoderSnapshot { 27public: 28 VkDecoderSnapshot(); 29 ~VkDecoderSnapshot(); 30 31 void save(android::base::Stream* stream); 32 void load(android::base::Stream* stream, emugl::GfxApiLogger& gfx_logger, 33 emugl::HealthMonitor<>* healthMonitor); 34 void createExtraHandlesForNextApi(const uint64_t* created, uint32_t count); 35""" 36 37decoder_snapshot_decl_postamble = """ 38private: 39 class Impl; 40 std::unique_ptr<Impl> mImpl; 41 42}; 43""" 44 45decoder_snapshot_impl_preamble =""" 46 47using namespace gfxstream::vk; 48using emugl::GfxApiLogger; 49using emugl::HealthMonitor; 50 51class VkDecoderSnapshot::Impl { 52public: 53 Impl() { } 54 55 void save(android::base::Stream* stream) { 56 mReconstruction.save(stream); 57 } 58 59 void load(android::base::Stream* stream, GfxApiLogger& gfx_logger, 60 HealthMonitor<>* healthMonitor) { 61 mReconstruction.load(stream, gfx_logger, healthMonitor); 62 } 63 64 void createExtraHandlesForNextApi(const uint64_t* created, uint32_t count) { 65 mLock.lock(); 66 mReconstruction.createExtraHandlesForNextApi(created, count); 67 } 68""" 69 70decoder_snapshot_impl_postamble = """ 71private: 72 android::base::Lock mLock; 73 VkReconstruction mReconstruction; 74}; 75 76VkDecoderSnapshot::VkDecoderSnapshot() : 77 mImpl(new VkDecoderSnapshot::Impl()) { } 78 79void VkDecoderSnapshot::save(android::base::Stream* stream) { 80 mImpl->save(stream); 81} 82 83void VkDecoderSnapshot::load(android::base::Stream* stream, GfxApiLogger& gfx_logger, 84 HealthMonitor<>* healthMonitor) { 85 mImpl->load(stream, gfx_logger, healthMonitor); 86} 87 88void VkDecoderSnapshot::createExtraHandlesForNextApi(const uint64_t* created, uint32_t count) { 89 mImpl->createExtraHandlesForNextApi(created, count); 90} 91 92VkDecoderSnapshot::~VkDecoderSnapshot() = default; 93""" 94 95AUXILIARY_SNAPSHOT_API_BASE_PARAM_COUNT = 3 96 97AUXILIARY_SNAPSHOT_API_PARAM_NAMES = [ 98 "input_result", 99] 100 101# Vulkan handle dependencies. 102# (a, b): a depends on b 103SNAPSHOT_HANDLE_DEPENDENCIES = [ 104 # Dispatchable handle types 105 ("VkCommandBuffer", "VkCommandPool"), 106 ("VkCommandPool", "VkDevice"), 107 ("VkQueue", "VkDevice"), 108 ("VkDevice", "VkPhysicalDevice"), 109 ("VkPhysicalDevice", "VkInstance")] + \ 110 list(map(lambda handleType : (handleType, "VkDevice"), NON_DISPATCHABLE_HANDLE_TYPES)) 111 112handleDependenciesDict = dict(SNAPSHOT_HANDLE_DEPENDENCIES) 113 114def extract_deps_vkAllocateMemory(param, access, lenExpr, api, cgen): 115 cgen.stmt("const VkMemoryDedicatedAllocateInfo* dedicatedAllocateInfo = vk_find_struct<VkMemoryDedicatedAllocateInfo>(pAllocateInfo)"); 116 cgen.beginIf("dedicatedAllocateInfo"); 117 cgen.beginIf("dedicatedAllocateInfo->image") 118 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \ 119 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkImage(dedicatedAllocateInfo->image)")) 120 cgen.endIf() 121 cgen.beginIf("dedicatedAllocateInfo->buffer") 122 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \ 123 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkBuffer(dedicatedAllocateInfo->buffer)")) 124 cgen.endIf() 125 cgen.endIf() 126 127def extract_deps_vkAllocateCommandBuffers(param, access, lenExpr, api, cgen): 128 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \ 129 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkCommandPool(pAllocateInfo->commandPool)")) 130 131def extract_deps_vkAllocateDescriptorSets(param, access, lenExpr, api, cgen): 132 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \ 133 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkDescriptorPool(pAllocateInfo->descriptorPool)")) 134 135def extract_deps_vkUpdateDescriptorSets(param, access, lenExpr, api, cgen): 136 cgen.beginFor("uint32_t i = 0", "i < descriptorWriteCount", "++i") 137 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkDescriptorSet( pDescriptorWrites[i].dstSet))") 138 cgen.beginFor("uint32_t j = 0", "j < pDescriptorWrites[i].descriptorCount", "++j") 139 cgen.beginIf("(pDescriptorWrites[i].pImageInfo)") 140 cgen.beginIf("pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER") 141 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkSampler( pDescriptorWrites[i].pImageInfo[j].sampler))") 142 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkImageView( pDescriptorWrites[i].pImageInfo[j].imageView))") 143 cgen.endIf() 144 cgen.beginIf("pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER") 145 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkSampler( pDescriptorWrites[i].pImageInfo[j].sampler))") 146 cgen.endIf() 147 cgen.endIf() 148 cgen.beginIf("pDescriptorWrites[i].pBufferInfo"); 149 cgen.beginIf("pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER"); 150 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer( pDescriptorWrites[i].pBufferInfo[j].buffer))") 151 cgen.endIf() 152 cgen.endIf() 153 cgen.endFor() 154 cgen.endFor() 155 156def extract_deps_vkCreateImageView(param, access, lenExpr, api, cgen): 157 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::CREATED, VkReconstruction::BOUND_MEMORY)" % \ 158 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkImage(pCreateInfo->image)")) 159 160def extract_deps_vkCreateGraphicsPipelines(param, access, lenExpr, api, cgen): 161 cgen.beginFor("uint32_t i = 0", "i < createInfoCount", "++i") 162 cgen.beginFor("uint32_t j = 0", "j < pCreateInfos[i].stageCount", "++j") 163 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(%s + i), %s, (uint64_t)(uintptr_t)%s)" % \ 164 (access, 1, "unboxed_to_boxed_non_dispatchable_VkShaderModule(pCreateInfos[i].pStages[j].module)")) 165 cgen.endFor() 166 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(%s + i), %s, (uint64_t)(uintptr_t)%s)" % \ 167 (access, 1, "unboxed_to_boxed_non_dispatchable_VkRenderPass(pCreateInfos[i].renderPass)")) 168 cgen.endFor() 169 170def extract_deps_vkCreateFramebuffer(param, access, lenExpr, api, cgen): 171 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \ 172 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkRenderPass(pCreateInfo->renderPass)")) 173 cgen.beginFor("uint32_t i = 0", "i < pCreateInfo->attachmentCount" , "++i") 174 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \ 175 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkImageView(pCreateInfo->pAttachments[i])")) 176 cgen.endFor() 177 178def extract_deps_vkBindImageMemory(param, access, lenExpr, api, cgen): 179 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::BOUND_MEMORY)" % \ 180 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkDeviceMemory(memory)")) 181 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)((%s)[0]), VkReconstruction::BOUND_MEMORY)" % \ 182 (access, lenExpr, access)) 183 184def extract_deps_vkBindBufferMemory(param, access, lenExpr, api, cgen): 185 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::BOUND_MEMORY)" % \ 186 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkDeviceMemory(memory)")) 187 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)((%s)[0]), VkReconstruction::BOUND_MEMORY)" % \ 188 (access, lenExpr, access)) 189 190specialCaseDependencyExtractors = { 191 "vkAllocateCommandBuffers" : extract_deps_vkAllocateCommandBuffers, 192 "vkAllocateDescriptorSets" : extract_deps_vkAllocateDescriptorSets, 193 "vkAllocateMemory" : extract_deps_vkAllocateMemory, 194 "vkCreateImageView" : extract_deps_vkCreateImageView, 195 "vkCreateGraphicsPipelines" : extract_deps_vkCreateGraphicsPipelines, 196 "vkCreateFramebuffer" : extract_deps_vkCreateFramebuffer, 197 "vkBindImageMemory": extract_deps_vkBindImageMemory, 198 "vkBindBufferMemory": extract_deps_vkBindBufferMemory, 199 "vkUpdateDescriptorSets" : extract_deps_vkUpdateDescriptorSets, 200} 201 202apiSequences = { 203 "vkAllocateMemory" : ["vkAllocateMemory", "vkMapMemoryIntoAddressSpaceGOOGLE"] 204} 205 206apiCrreateExtraHandles = [ 207 "vkCreateDevice", 208 "vkCreateDescriptorPool", 209] 210 211@dataclass(frozen=True) 212class VkObjectState: 213 vk_object : str 214 state : str = "VkReconstruction::CREATED" 215 216# TODO: add vkBindImageMemory2 and vkBindBufferMemory2 into this list 217apiChangeState = { 218 "vkBindImageMemory": VkObjectState("image", "VkReconstruction::BOUND_MEMORY"), 219 "vkBindBufferMemory": VkObjectState("buffer", "VkReconstruction::BOUND_MEMORY"), 220} 221 222def api_special_implementation_vkBindImageMemory2(api, cgen): 223 childType = "VkImage" 224 parentType = "VkDeviceMemory" 225 childObj = "boxed_%s" % childType 226 parentObj = "boxed_%s" % parentType 227 cgen.stmt("android::base::AutoLock lock(mLock)") 228 cgen.beginFor("uint32_t i = 0", "i < bindInfoCount", "++i") 229 cgen.stmt("%s boxed_%s = unboxed_to_boxed_non_dispatchable_%s(pBindInfos[i].image)" 230 % (childType, childType, childType)) 231 cgen.stmt("%s boxed_%s = unboxed_to_boxed_non_dispatchable_%s(pBindInfos[i].memory)" 232 % (parentType, parentType, parentType)) 233 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)&%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::BOUND_MEMORY)" % \ 234 (childObj, "1", parentObj)) 235 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)&%s, %s, (uint64_t)(uintptr_t)%s, VkReconstruction::BOUND_MEMORY)" % \ 236 (childObj, "1", childObj)) 237 cgen.endFor() 238 239 cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()") 240 cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)") 241 cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name) 242 cgen.line("// Note: the implementation does not work with bindInfoCount > 1"); 243 cgen.beginFor("uint32_t i = 0", "i < bindInfoCount", "++i") 244 cgen.stmt("%s boxed_%s = unboxed_to_boxed_non_dispatchable_%s(pBindInfos[i].image)" 245 % (childType, childType, childType)) 246 cgen.stmt(f"mReconstruction.forEachHandleAddApi((const uint64_t*)&{childObj}, {1}, apiHandle, VkReconstruction::BOUND_MEMORY)") 247 cgen.endFor() 248 249apiSpecialImplementation = { 250 "vkBindImageMemory2": api_special_implementation_vkBindImageMemory2, 251 "vkBindImageMemory2KHR": api_special_implementation_vkBindImageMemory2, 252} 253 254apiModifies = { 255 "vkMapMemoryIntoAddressSpaceGOOGLE" : ["memory"], 256 "vkGetBlobGOOGLE" : ["memory"], 257 "vkBeginCommandBuffer" : ["commandBuffer"], 258 "vkEndCommandBuffer" : ["commandBuffer"], 259} 260 261apiActions = { 262 "vkUpdateDescriptorSets" : ["pDescriptorWrites"], 263} 264 265apiClearModifiers = { 266 "vkResetCommandBuffer" : ["commandBuffer"], 267} 268 269delayedDestroys = [ 270 "vkDestroyShaderModule", 271] 272 273# The following types are created and cached by other commands. 274# Thus we should not snapshot their "create" commands. 275skipCreatorSnapshotTypes = [ 276 "VkQueue", # created by vkCreateDevice 277] 278 279def is_state_change_operation(api, param): 280 if param.isCreatedBy(api) and param.typeName not in skipCreatorSnapshotTypes: 281 return True 282 if api.name in apiChangeState: 283 if param.paramName == apiChangeState[api.name].vk_object: 284 return True 285 return False 286 287def get_target_state(api, param): 288 if param.isCreatedBy(api): 289 return "VkReconstruction::CREATED" 290 if api.name in apiActions: 291 return "VkReconstruction::CREATED" 292 if api.name in apiChangeState: 293 if param.paramName == apiChangeState[api.name].vk_object: 294 return apiChangeState[api.name].state 295 return None 296 297def is_action_operation(api, param): 298 if api.name in apiActions: 299 if param.paramName in apiActions[api.name]: 300 return True 301 return False 302 303def is_modify_operation(api, param): 304 if api.name in apiModifies: 305 if param.paramName in apiModifies[api.name]: 306 return True 307 if api.name.startswith('vkCmd') and param.paramName == 'commandBuffer': 308 return True 309 return False 310 311def is_clear_modifier_operation(api, param): 312 if api.name in apiClearModifiers: 313 if param.paramName in apiClearModifiers[api.name]: 314 return True 315 316 317def emit_impl(typeInfo, api, cgen): 318 if api.name in apiSpecialImplementation: 319 apiSpecialImplementation[api.name](api, cgen) 320 for p in api.parameters: 321 if not (p.isHandleType): 322 continue 323 324 lenExpr = cgen.generalLengthAccess(p) 325 lenAccessGuard = cgen.generalLengthAccessGuard(p) 326 327 if lenExpr is None: 328 lenExpr = "1" 329 330 # Note that in vkCreate*, the last parameter (the output) is boxed. But all input parameters are unboxed. 331 332 if p.pointerIndirectionLevels > 0: 333 access = p.paramName 334 else: 335 access = "(&%s)" % p.paramName 336 337 if is_state_change_operation(api, p): 338 if p.isCreatedBy(api): 339 boxed_access = access 340 else: 341 cgen.stmt("%s boxed_%s = unboxed_to_boxed_non_dispatchable_%s(%s[0])" % (p.typeName, p.typeName, p.typeName, access)) 342 boxed_access = "&boxed_%s" % p.typeName 343 if p.pointerIndirectionLevels > 0: 344 cgen.stmt("if (!%s) return" % access) 345 isCreateExtraHandleApi = api.name in apiCrreateExtraHandles 346 if isCreateExtraHandleApi: 347 cgen.stmt("mLock.tryLock()"); 348 else: 349 cgen.stmt("android::base::AutoLock lock(mLock)") 350 cgen.line("// %s create" % p.paramName) 351 if p.isCreatedBy(api): 352 cgen.stmt("mReconstruction.addHandles((const uint64_t*)%s, %s)" % (boxed_access, lenExpr)); 353 354 if p.isCreatedBy(api) and p.typeName in handleDependenciesDict: 355 dependsOnType = handleDependenciesDict[p.typeName]; 356 for p2 in api.parameters: 357 if p2.typeName == dependsOnType: 358 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % (boxed_access, lenExpr, p2.paramName)) 359 if api.name in specialCaseDependencyExtractors: 360 specialCaseDependencyExtractors[api.name](p, boxed_access, lenExpr, api, cgen) 361 362 cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()") 363 cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)") 364 cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name) 365 if lenAccessGuard is not None: 366 cgen.beginIf(lenAccessGuard) 367 cgen.stmt(f"mReconstruction.forEachHandleAddApi((const uint64_t*){boxed_access}, {lenExpr}, apiHandle, {get_target_state(api, p)})") 368 if p.isCreatedBy(api): 369 cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiHandle, (const uint64_t*)%s, %s)" % (boxed_access, lenExpr)) 370 if lenAccessGuard is not None: 371 cgen.endIf() 372 if isCreateExtraHandleApi: 373 cgen.stmt("mLock.unlock()") 374 375 if p.isDestroyedBy(api): 376 cgen.stmt("android::base::AutoLock lock(mLock)") 377 cgen.line("// %s destroy" % p.paramName) 378 if lenAccessGuard is not None: 379 cgen.beginIf(lenAccessGuard) 380 shouldRecursiveDestroy = "false" if api.name in delayedDestroys else "true" 381 cgen.stmt("mReconstruction.removeHandles((const uint64_t*)%s, %s, %s)" % (access, lenExpr, shouldRecursiveDestroy)); 382 if lenAccessGuard is not None: 383 cgen.endIf() 384 385 if is_action_operation(api, p): 386 cgen.stmt("android::base::AutoLock lock(mLock)") 387 cgen.line("// %s action" % p.paramName) 388 cgen.stmt("VkDecoderGlobalState* m_state = VkDecoderGlobalState::get()") 389 cgen.beginIf("m_state->batchedDescriptorSetUpdateEnabled()") 390 cgen.stmt("return") 391 cgen.endIf(); 392 cgen.stmt("uint64_t handle = m_state->newGlobalVkGenericHandle()") 393 cgen.stmt("mReconstruction.addHandles((const uint64_t*)(&handle), 1)"); 394 cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()") 395 cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)") 396 cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name) 397 if api.name in specialCaseDependencyExtractors: 398 specialCaseDependencyExtractors[api.name](p, None, None, api, cgen) 399 cgen.stmt(f"mReconstruction.forEachHandleAddApi((const uint64_t*)(&handle), 1, apiHandle, {get_target_state(api, p)})") 400 cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiHandle, (const uint64_t*)(&handle), 1)") 401 402 elif is_modify_operation(api, p) or is_clear_modifier_operation(api, p): 403 cgen.stmt("android::base::AutoLock lock(mLock)") 404 cgen.line("// %s modify" % p.paramName) 405 cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()") 406 cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)") 407 cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name) 408 if lenAccessGuard is not None: 409 cgen.beginIf(lenAccessGuard) 410 cgen.beginFor("uint32_t i = 0", "i < %s" % lenExpr, "++i") 411 if p.isNonDispatchableHandleType(): 412 cgen.stmt("%s boxed = unboxed_to_boxed_non_dispatchable_%s(%s[i])" % (p.typeName, p.typeName, access)) 413 else: 414 cgen.line("// %s is already boxed, no need to box again" % p.paramName) 415 cgen.stmt("%s boxed = %s(%s[i])" % (p.typeName, p.typeName, access)) 416 if is_modify_operation(api, p): 417 cgen.stmt("mReconstruction.forEachHandleAddModifyApi((const uint64_t*)(&boxed), 1, apiHandle)") 418 else: # is clear modifier operation 419 cgen.stmt("mReconstruction.forEachHandleClearModifyApi((const uint64_t*)(&boxed), 1)") 420 cgen.endFor() 421 if lenAccessGuard is not None: 422 cgen.endIf() 423 424def emit_passthrough_to_impl(typeInfo, api, cgen): 425 cgen.vkApiCall(api, customPrefix = "mImpl->") 426 427class VulkanDecoderSnapshot(VulkanWrapperGenerator): 428 def __init__(self, module, typeInfo): 429 VulkanWrapperGenerator.__init__(self, module, typeInfo) 430 431 self.typeInfo = typeInfo 432 433 self.cgenHeader = CodeGen() 434 self.cgenHeader.incrIndent() 435 436 self.cgenImpl = CodeGen() 437 438 self.currentFeature = None 439 440 self.feature_apis = [] 441 442 def onBegin(self,): 443 self.module.appendHeader(decoder_snapshot_decl_preamble) 444 self.module.appendImpl(decoder_snapshot_impl_preamble) 445 446 def onBeginFeature(self, featureName, featureType): 447 VulkanWrapperGenerator.onBeginFeature(self, featureName, featureType) 448 self.currentFeature = featureName 449 450 def onGenCmd(self, cmdinfo, name, alias): 451 VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias) 452 453 api = self.typeInfo.apis[name] 454 455 additionalParams = [ \ 456 makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"), 457 makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"), 458 makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "pool"),] 459 460 if api.retType.typeName != "void": 461 additionalParams.append( \ 462 makeVulkanTypeSimple(False, api.retType.typeName, 0, "input_result")) 463 464 apiForSnapshot = \ 465 api.withCustomParameters( \ 466 additionalParams + \ 467 api.parameters).withCustomReturnType( \ 468 makeVulkanTypeSimple(False, "void", 0, "void")) 469 470 self.feature_apis.append((self.currentFeature, apiForSnapshot)) 471 472 self.cgenHeader.stmt(self.cgenHeader.makeFuncProto(apiForSnapshot)) 473 self.module.appendHeader(self.cgenHeader.swapCode()) 474 475 self.cgenImpl.emitFuncImpl( \ 476 apiForSnapshot, lambda cgen: emit_impl(self.typeInfo, apiForSnapshot, cgen)) 477 self.module.appendImpl(self.cgenImpl.swapCode()) 478 479 def onEnd(self,): 480 self.module.appendHeader(decoder_snapshot_decl_postamble) 481 self.module.appendImpl(decoder_snapshot_impl_postamble) 482 self.cgenHeader.decrIndent() 483 484 for feature, api in self.feature_apis: 485 if feature is not None: 486 self.cgenImpl.line("#ifdef %s" % feature) 487 488 apiImplShell = \ 489 api.withModifiedName("VkDecoderSnapshot::" + api.name) 490 491 self.cgenImpl.emitFuncImpl( \ 492 apiImplShell, lambda cgen: emit_passthrough_to_impl(self.typeInfo, api, cgen)) 493 494 if feature is not None: 495 self.cgenImpl.line("#endif") 496 497 self.module.appendImpl(self.cgenImpl.swapCode()) 498 499