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