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