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