1from .common.codegen import CodeGen, VulkanWrapperGenerator, VulkanAPIWrapper 2from .common.vulkantypes import \ 3 VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, DISPATCHABLE_HANDLE_TYPES, NON_DISPATCHABLE_HANDLE_TYPES 4 5from .transform import TransformCodegen, genTransformsForVulkanType 6 7from .wrapperdefs import API_PREFIX_MARSHAL 8from .wrapperdefs import API_PREFIX_UNMARSHAL 9from .wrapperdefs import VULKAN_STREAM_TYPE 10 11from copy import copy 12 13decoder_snapshot_decl_preamble = """ 14 15namespace android { 16namespace base { 17class BumpPool; 18class Stream; 19} // namespace base { 20} // namespace android { 21 22class VkDecoderSnapshot { 23public: 24 VkDecoderSnapshot(); 25 ~VkDecoderSnapshot(); 26 27 void save(android::base::Stream* stream); 28 void load(android::base::Stream* stream); 29""" 30 31decoder_snapshot_decl_postamble = """ 32private: 33 class Impl; 34 std::unique_ptr<Impl> mImpl; 35 36}; 37""" 38 39decoder_snapshot_impl_preamble =""" 40 41using namespace goldfish_vk; 42 43class VkDecoderSnapshot::Impl { 44public: 45 Impl() { } 46 47 void save(android::base::Stream* stream) { 48 mReconstruction.save(stream); 49 } 50 51 void load(android::base::Stream* stream) { 52 mReconstruction.load(stream); 53 } 54 55""" 56 57decoder_snapshot_impl_postamble = """ 58private: 59 android::base::Lock mLock; 60 VkReconstruction mReconstruction; 61}; 62 63VkDecoderSnapshot::VkDecoderSnapshot() : 64 mImpl(new VkDecoderSnapshot::Impl()) { } 65 66void VkDecoderSnapshot::save(android::base::Stream* stream) { 67 mImpl->save(stream); 68} 69 70void VkDecoderSnapshot::load(android::base::Stream* stream) { 71 mImpl->load(stream); 72} 73 74VkDecoderSnapshot::~VkDecoderSnapshot() = default; 75""" 76 77AUXILIARY_SNAPSHOT_API_BASE_PARAM_COUNT = 3 78 79AUXILIARY_SNAPSHOT_API_PARAM_NAMES = [ 80 "input_result", 81] 82 83# Vulkan handle dependencies. 84# (a, b): a depends on b 85SNAPSHOT_HANDLE_DEPENDENCIES = [ 86 # Dispatchable handle types 87 ("VkCommandBuffer", "VkCommandPool"), 88 ("VkCommandPool", "VkDevice"), 89 ("VkQueue", "VkDevice"), 90 ("VkDevice", "VkPhysicalDevice"), 91 ("VkPhysicalDevice", "VkInstance")] + \ 92 list(map(lambda handleType : (handleType, "VkDevice"), NON_DISPATCHABLE_HANDLE_TYPES)) 93 94handleDependenciesDict = dict(SNAPSHOT_HANDLE_DEPENDENCIES) 95 96def extract_deps_vkAllocateCommandBuffers(param, access, lenExpr, api, cgen): 97 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % \ 98 (access, lenExpr, "unboxed_to_boxed_non_dispatchable_VkCommandPool(pAllocateInfo->commandPool)")) 99 100specialCaseDependencyExtractors = { 101 "vkAllocateCommandBuffers" : extract_deps_vkAllocateCommandBuffers, 102} 103 104apiSequences = { 105 "vkAllocateMemory" : ["vkAllocateMemory", "vkMapMemoryIntoAddressSpaceGOOGLE"] 106} 107 108apiModifies = { 109 "vkMapMemoryIntoAddressSpaceGOOGLE" : ["memory"], 110} 111 112def is_modify_operation(api, param): 113 if api.name in apiModifies: 114 if param.paramName in apiModifies[api.name]: 115 return True 116 return False 117 118def emit_impl(typeInfo, api, cgen): 119 120 cgen.line("// TODO: Implement") 121 122 for p in api.parameters: 123 if not (p.isHandleType): 124 continue 125 126 lenExpr = cgen.generalLengthAccess(p) 127 lenAccessGuard = cgen.generalLengthAccessGuard(p) 128 129 if lenExpr is None: 130 lenExpr = "1" 131 132 if p.pointerIndirectionLevels > 0: 133 access = p.paramName 134 else: 135 access = "(&%s)" % p.paramName 136 137 if p.isCreatedBy(api): 138 cgen.stmt("android::base::AutoLock lock(mLock)") 139 cgen.line("// %s create" % p.paramName) 140 cgen.stmt("mReconstruction.addHandles((const uint64_t*)%s, %s)" % (access, lenExpr)); 141 142 if p.typeName in handleDependenciesDict: 143 dependsOnType = handleDependenciesDict[p.typeName]; 144 for p2 in api.parameters: 145 if p2.typeName == dependsOnType: 146 cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)%s, %s, (uint64_t)(uintptr_t)%s)" % (access, lenExpr, p2.paramName)) 147 if api.name in specialCaseDependencyExtractors: 148 specialCaseDependencyExtractors[api.name](p, access, lenExpr, api, cgen) 149 150 cgen.stmt("if (!%s) return" % access) 151 cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()") 152 cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)") 153 cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name) 154 if lenAccessGuard is not None: 155 cgen.beginIf(lenAccessGuard) 156 cgen.stmt("mReconstruction.forEachHandleAddApi((const uint64_t*)%s, %s, apiHandle)" % (access, lenExpr)) 157 cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiHandle, (const uint64_t*)%s, %s)" % (access, lenExpr)) 158 if lenAccessGuard is not None: 159 cgen.endIf() 160 161 if p.isDestroyedBy(api): 162 cgen.stmt("android::base::AutoLock lock(mLock)") 163 cgen.line("// %s destroy" % p.paramName) 164 if lenAccessGuard is not None: 165 cgen.beginIf(lenAccessGuard) 166 cgen.stmt("mReconstruction.removeHandles((const uint64_t*)%s, %s)" % (access, lenExpr)); 167 if lenAccessGuard is not None: 168 cgen.endIf() 169 170 if is_modify_operation(api, p): 171 cgen.stmt("android::base::AutoLock lock(mLock)") 172 cgen.line("// %s modify" % p.paramName) 173 cgen.stmt("auto apiHandle = mReconstruction.createApiInfo()") 174 cgen.stmt("auto apiInfo = mReconstruction.getApiInfo(apiHandle)") 175 cgen.stmt("mReconstruction.setApiTrace(apiInfo, OP_%s, snapshotTraceBegin, snapshotTraceBytes)" % api.name) 176 if lenAccessGuard is not None: 177 cgen.beginIf(lenAccessGuard) 178 cgen.beginFor("uint32_t i = 0", "i < %s" % lenExpr, "++i") 179 if p.isNonDispatchableHandleType(): 180 cgen.stmt("%s boxed = unboxed_to_boxed_non_dispatchable_%s(%s[i])" % (p.typeName, p.typeName, access)) 181 else: 182 cgen.stmt("%s boxed = unboxed_to_boxed_%s(%s[i])" % (p.typeName, p.typeName, access)) 183 cgen.stmt("mReconstruction.forEachHandleAddModifyApi((const uint64_t*)(&boxed), 1, apiHandle)") 184 cgen.endFor() 185 if lenAccessGuard is not None: 186 cgen.endIf() 187 188def emit_passthrough_to_impl(typeInfo, api, cgen): 189 cgen.vkApiCall(api, customPrefix = "mImpl->") 190 191class VulkanDecoderSnapshot(VulkanWrapperGenerator): 192 def __init__(self, module, typeInfo): 193 VulkanWrapperGenerator.__init__(self, module, typeInfo) 194 195 self.typeInfo = typeInfo 196 197 self.cgenHeader = CodeGen() 198 self.cgenHeader.incrIndent() 199 200 self.cgenImpl = CodeGen() 201 202 self.currentFeature = None 203 204 self.feature_apis = [] 205 206 def onBegin(self,): 207 self.module.appendHeader(decoder_snapshot_decl_preamble) 208 self.module.appendImpl(decoder_snapshot_impl_preamble) 209 210 def onBeginFeature(self, featureName): 211 VulkanWrapperGenerator.onBeginFeature(self, featureName) 212 self.currentFeature = featureName 213 214 def onGenCmd(self, cmdinfo, name, alias): 215 VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias) 216 217 api = self.typeInfo.apis[name] 218 219 additionalParams = [ \ 220 makeVulkanTypeSimple(True, "uint8_t", 1, "snapshotTraceBegin"), 221 makeVulkanTypeSimple(False, "size_t", 0, "snapshotTraceBytes"), 222 makeVulkanTypeSimple(False, "android::base::BumpPool", 1, "pool"),] 223 224 if api.retType.typeName != "void": 225 additionalParams.append( \ 226 makeVulkanTypeSimple(False, api.retType.typeName, 0, "input_result")) 227 228 apiForSnapshot = \ 229 api.withCustomParameters( \ 230 additionalParams + \ 231 api.parameters).withCustomReturnType( \ 232 makeVulkanTypeSimple(False, "void", 0, "void")) 233 234 self.feature_apis.append((self.currentFeature, apiForSnapshot)) 235 236 self.cgenHeader.stmt(self.cgenHeader.makeFuncProto(apiForSnapshot)) 237 self.module.appendHeader(self.cgenHeader.swapCode()) 238 239 self.cgenImpl.emitFuncImpl( \ 240 apiForSnapshot, lambda cgen: emit_impl(self.typeInfo, apiForSnapshot, cgen)) 241 self.module.appendImpl(self.cgenImpl.swapCode()) 242 243 def onEnd(self,): 244 self.module.appendHeader(decoder_snapshot_decl_postamble) 245 self.module.appendImpl(decoder_snapshot_impl_postamble) 246 self.cgenHeader.decrIndent() 247 248 for feature, api in self.feature_apis: 249 if feature is not None: 250 self.cgenImpl.line("#ifdef %s" % feature) 251 252 apiImplShell = \ 253 api.withModifiedName("VkDecoderSnapshot::" + api.name) 254 255 self.cgenImpl.emitFuncImpl( \ 256 apiImplShell, lambda cgen: emit_passthrough_to_impl(self.typeInfo, api, cgen)) 257 258 if feature is not None: 259 self.cgenImpl.line("#endif") 260 261 self.module.appendImpl(self.cgenImpl.swapCode()) 262 263