gfxstream: use VkSnapshotApiCallHandle outside of VkReconstruction

... as VkSnapshotApiCallInfo* is a pointer into a
std::vector<VkSnapshotApiCallInfo> which can be invalidated during
multi threaded VK usage when the std::vector<> is resized.

Test: bazel test common/end2end:gfxstream_end2end_tests \
      --graphics_drivers=gles_angle_vulkan_swiftshader \
      --test_arg="--gtest_filter=*MultiThreadedResetCommandBuffer*VulkanSnapshots*" \
      --test_arg="--gtest_repeat=100" \
      --test_output=streamed

Reviewed-by: Marcin Radomski <dextero@google.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35416>
This commit is contained in:
Jason Macnak 2025-06-04 12:56:26 -07:00 committed by Marge Bot
parent 0f05988640
commit 7fb8d85c26
4 changed files with 67 additions and 51 deletions

View file

@ -36,7 +36,7 @@ GLOBAL_COMMANDS_WITHOUT_DISPATCH = [
"vkEnumerateInstanceLayerProperties",
]
SNAPSHOT_API_CALL_INFO_VARNAME = "snapshotApiCallInfo"
SNAPSHOT_API_CALL_HANDLE_VARNAME = "snapshotApiCallHandle"
global_state_prefix = "m_state->on_"
@ -376,9 +376,9 @@ def emit_global_state_wrapped_call(api, cgen, context):
if delay:
cgen.line("std::function<void()> delayed_remove_callback = [vk, %s]() {" % ", ".join(coreCustomParams))
cgen.stmt("auto m_state = VkDecoderGlobalState::get()")
customParams = ["nullptr", "nullptr"] + coreCustomParams
customParams = ["nullptr", "kInvalidSnapshotApiCallHandle"] + coreCustomParams
else:
customParams = ["&m_pool", SNAPSHOT_API_CALL_INFO_VARNAME] + coreCustomParams
customParams = ["&m_pool", SNAPSHOT_API_CALL_HANDLE_VARNAME] + coreCustomParams
if context:
customParams += ["context"]
@ -490,7 +490,7 @@ def emit_seqno_incr(api, cgen):
def emit_snapshot(typeInfo, api, cgen):
additionalParams = [ \
makeVulkanTypeSimple(False, "gfxstream::base::BumpPool", 1, "&m_pool"),
makeVulkanTypeSimple(True, "VkSnapshotApiCallInfo", 1, SNAPSHOT_API_CALL_INFO_VARNAME),
makeVulkanTypeSimple(True, "VkSnapshotApiCallHandle", 1, SNAPSHOT_API_CALL_HANDLE_VARNAME),
makeVulkanTypeSimple(True, "uint8_t", 1, "packet"),
makeVulkanTypeSimple(False, "size_t", 0, "packetLen"),
]
@ -969,11 +969,11 @@ size_t VkDecoder::Impl::decode(void* buf, size_t len, IOStream* ioStream,
""")
self.cgen.line("""
VkSnapshotApiCallInfo* %s = nullptr;
VkSnapshotApiCallHandle %s = kInvalidSnapshotApiCallHandle;
if (m_snapshotsEnabled) {
%s = m_state->snapshot()->createApiCallInfo();
}
""" % (SNAPSHOT_API_CALL_INFO_VARNAME, SNAPSHOT_API_CALL_INFO_VARNAME))
""" % (SNAPSHOT_API_CALL_HANDLE_VARNAME, SNAPSHOT_API_CALL_HANDLE_VARNAME))
self.cgen.line("""
gfx_logger.recordCommandExecution();
@ -1017,7 +1017,7 @@ size_t VkDecoder::Impl::decode(void* buf, size_t len, IOStream* ioStream,
if (m_snapshotsEnabled) {
m_state->snapshot()->destroyApiCallInfoIfUnused(%s);
}
""" % (SNAPSHOT_API_CALL_INFO_VARNAME))
""" % (SNAPSHOT_API_CALL_HANDLE_VARNAME))
self.cgen.stmt("m_pool.freeAll()")
self.cgen.stmt("return ptr - (unsigned char *)buf")
@ -1029,7 +1029,7 @@ size_t VkDecoder::Impl::decode(void* buf, size_t len, IOStream* ioStream,
if (m_snapshotsEnabled) {
m_state->snapshot()->destroyApiCallInfoIfUnused(%s);
}
""" % (SNAPSHOT_API_CALL_INFO_VARNAME))
""" % (SNAPSHOT_API_CALL_HANDLE_VARNAME))
self.cgen.stmt("ptr += packetLen")
self.cgen.stmt("vkStream->clearPool()")

View file

@ -39,8 +39,13 @@ class VkDecoderSnapshot {
void saveReplayBuffers(gfxstream::Stream* stream);
static void loadReplayBuffers(gfxstream::Stream* stream, std::vector<uint64_t>* outHandleBuffer, std::vector<uint8_t>* outDecoderBuffer);
VkSnapshotApiCallInfo* createApiCallInfo();
void destroyApiCallInfoIfUnused(VkSnapshotApiCallInfo* info);
VkSnapshotApiCallHandle createApiCallInfo();
void destroyApiCallInfoIfUnused(VkSnapshotApiCallHandle handle);
// Performs bookkeeping to track that a given api call created the given VkObject handles.
// This is a public function so that `VkDecoderGlobalState` can inform snapshot of any
// additional handles created while emulating features.
void addOrderedBoxedHandlesCreatedByCall(VkSnapshotApiCallHandle apiCallHandle, VkObjectHandle* boxedHandles, uint32_t boxedHandlesCount);
"""
decoder_snapshot_decl_postamble = """
@ -77,15 +82,21 @@ class VkDecoderSnapshot::Impl {
VkReconstruction::loadReplayBuffers(stream, outHandleBuffer, outDecoderBuffer);
}
VkSnapshotApiCallInfo* createApiCallInfo() {
VkSnapshotApiCallHandle createApiCallInfo() {
std::lock_guard<std::mutex> lock(mReconstructionMutex);
return mReconstruction.createApiCallInfo();
}
void destroyApiCallInfoIfUnused(VkSnapshotApiCallInfo* info) {
void destroyApiCallInfoIfUnused(VkSnapshotApiCallHandle apiCallHandle) {
std::lock_guard<std::mutex> lock(mReconstructionMutex);
return mReconstruction.destroyApiCallInfoIfUnused(info);
return mReconstruction.destroyApiCallInfoIfUnused(apiCallHandle);
}
void addOrderedBoxedHandlesCreatedByCall(VkSnapshotApiCallHandle apiCallHandle, VkObjectHandle* boxedHandles, uint32_t boxedHandlesCount) {
std::lock_guard<std::mutex> lock(mReconstructionMutex);
return mReconstruction.addOrderedBoxedHandlesCreatedByCall(apiCallHandle, boxedHandles, boxedHandlesCount);
}
"""
decoder_snapshot_impl_postamble = """
@ -110,12 +121,16 @@ void VkDecoderSnapshot::loadReplayBuffers(gfxstream::Stream* stream, std::vector
VkDecoderSnapshot::Impl::loadReplayBuffers(stream, outHandleBuffer, outDecoderBuffer);
}
VkSnapshotApiCallInfo* VkDecoderSnapshot::createApiCallInfo() {
VkSnapshotApiCallHandle VkDecoderSnapshot::createApiCallInfo() {
return mImpl->createApiCallInfo();
}
void VkDecoderSnapshot::destroyApiCallInfoIfUnused(VkSnapshotApiCallInfo* info) {
mImpl->destroyApiCallInfoIfUnused(info);
void VkDecoderSnapshot::destroyApiCallInfoIfUnused(VkSnapshotApiCallHandle handle) {
mImpl->destroyApiCallInfoIfUnused(handle);
}
void VkDecoderSnapshot::addOrderedBoxedHandlesCreatedByCall(VkSnapshotApiCallHandle apiCallHandle, VkObjectHandle* boxedHandles, uint32_t boxedHandlesCount) {
mImpl->addOrderedBoxedHandlesCreatedByCall(apiCallHandle, boxedHandles, boxedHandlesCount);
}
VkDecoderSnapshot::~VkDecoderSnapshot() = default;
@ -257,18 +272,17 @@ def api_special_implementation_common(api, cgen, tag_vk):
cgen.stmt("VkDecoderGlobalState* m_state = VkDecoderGlobalState::get()")
cgen.stmt("uint64_t handle = m_state->newGlobalVkGenericHandle(%s)" % tag_vk)
cgen.stmt("mReconstruction.addHandles((const uint64_t*)(&handle), 1)")
cgen.stmt("mReconstruction.forEachHandleAddApi((const uint64_t*)(&handle), 1, apiCallInfo->handle, VkReconstruction::CREATED)")
cgen.stmt("auto apiCallHandle = apiCallInfo->handle")
cgen.stmt("mReconstruction.forEachHandleAddApi((const uint64_t*)(&handle), 1, apiCallHandle, VkReconstruction::CREATED)")
cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiCallHandle, (const uint64_t*)(&handle), 1)")
cgen.stmt("mReconstruction.setApiTrace(apiCallInfo, apiCallPacket, apiCallPacketSize)")
cgen.stmt("mReconstruction.setApiTrace(apiCallHandle, apiCallPacket, apiCallPacketSize)")
def api_special_implementation_vkCmdPipelineBarrier(api, cgen):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
cgen.beginFor("uint32_t i = 0", "i < bufferMemoryBarrierCount", "++i")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer( pBufferMemoryBarriers[i].buffer))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer( pBufferMemoryBarriers[i].buffer))")
cgen.endFor()
cgen.beginFor("uint32_t i = 0", "i < imageMemoryBarrierCount", "++i")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkImage( pImageMemoryBarriers[i].image))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkImage( pImageMemoryBarriers[i].image))")
cgen.endFor()
def api_special_implementation_vkUpdateDescriptorSetWithTemplateSizedGOOGLE(api, cgen):
@ -279,15 +293,14 @@ def api_special_implementation_vkUpdateDescriptorSetWithTemplateSizedGOOGLE(api,
cgen.endIf();
cgen.stmt("uint64_t handle = m_state->newGlobalVkGenericHandle(Tag_VkUpdateDescriptorSets)")
cgen.stmt("mReconstruction.addHandles((const uint64_t*)(&handle), 1)")
cgen.stmt("auto apiCallHandle = apiCallInfo->handle")
cgen.stmt("mReconstruction.setApiTrace(apiCallInfo, apiCallPacket, apiCallPacketSize)")
cgen.stmt("mReconstruction.setApiTrace(apiCallHandle, apiCallPacket, apiCallPacketSize)")
cgen.stmt("mReconstruction.addHandleDependency( (const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)device)")
cgen.stmt("mReconstruction.forEachHandleAddApi((const uint64_t*)(&handle), 1, apiCallHandle, VkReconstruction::CREATED)")
cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiCallHandle, (const uint64_t*)(&handle), 1)")
def api_special_implementation_vkCmdBeginRenderPass(api, cgen):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkFramebuffer( pRenderPassBegin->framebuffer))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkFramebuffer( pRenderPassBegin->framebuffer))")
def api_special_implementation_vkMapMemoryIntoAddressSpaceGOOGLE(api, cgen):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
@ -295,34 +308,33 @@ def api_special_implementation_vkMapMemoryIntoAddressSpaceGOOGLE(api, cgen):
cgen.stmt("uint64_t handle = m_state->newGlobalVkGenericHandle(Tag_VkMapMemory)")
cgen.stmt("mReconstruction.addHandles((const uint64_t*)(&handle), 1)")
cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkDeviceMemory(memory))")
cgen.stmt("mReconstruction.forEachHandleAddApi((const uint64_t*)(&handle), 1, apiCallInfo->handle, VkReconstruction::CREATED)")
cgen.stmt("auto apiCallHandle = apiCallInfo->handle")
cgen.stmt("mReconstruction.forEachHandleAddApi((const uint64_t*)(&handle), 1, apiCallHandle, VkReconstruction::CREATED)")
cgen.stmt("mReconstruction.setCreatedHandlesForApi(apiCallHandle, (const uint64_t*)(&handle), 1)")
cgen.stmt("mReconstruction.setApiTrace(apiCallInfo, apiCallPacket, apiCallPacketSize)")
cgen.stmt("mReconstruction.setApiTrace(apiCallHandle, apiCallPacket, apiCallPacketSize)")
def api_special_implementation_vkCmdBeginRenderPass(api, cgen):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkFramebuffer( pRenderPassBegin->framebuffer))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkFramebuffer( pRenderPassBegin->framebuffer))")
def api_special_implementation_vkCmdCopyBufferToImage(api, cgen):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer(srcBuffer))")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkImage(dstImage))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer(srcBuffer))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkImage(dstImage))")
def api_special_implementation_vkCmdCopyBuffer(api, cgen):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer(srcBuffer))")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer(dstBuffer))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer(srcBuffer))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer(dstBuffer))")
def api_special_implementation_vkCmdBindVertexBuffers(api, cgen):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
cgen.beginFor("uint32_t i = 0", "i < bindingCount", "++i")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer(pBuffers[i]))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkBuffer(pBuffers[i]))")
cgen.endFor()
def api_special_implementation_vkCmdBindPipeline(api, cgen):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
cgen.stmt("apiCallInfo->depends.push_back( (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkPipeline(pipeline))")
cgen.stmt("mReconstruction.addApiCallDependencyOnVkObject(apiCallHandle, (uint64_t)(uintptr_t)unboxed_to_boxed_non_dispatchable_VkPipeline(pipeline))")
def api_special_implementation_vkResetCommandPool(api, cgen):
cgen.line("// Note: special implementation");
@ -337,10 +349,10 @@ def api_special_implementation_vkResetCommandBuffer(api, cgen):
def api_special_implementation_vkQueueFlushCommandsGOOGLE(api, cgen):
api_special_implementation_common(api, cgen, "Tag_VkCmdOp")
cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)commandBuffer)")
cgen.beginFor("uint32_t i = 0", "i < apiCallInfo->depends.size()", "++i")
cgen.stmt("auto parent = apiCallInfo->depends[i]")
cgen.stmt("mReconstruction.addHandleDependency((const uint64_t*)(&handle), 1, (uint64_t)(uintptr_t)parent)")
cgen.endFor()
cgen.line("// Track that `handle` depends on previously tracked dependencies (e.g. the handle for this `vkQueueFlushCommandsGOOGLE()` call depends on the `VkPipeline` handle from `vkCmdBindPipeline()`).")
cgen.stmt("mReconstruction.addHandleDependenciesForApiCallDependencies(apiCallHandle, handle)")
def api_special_implementation_vkBindBufferMemory(api, cgen):
api_special_implementation_common(api, cgen, "Tag_VkBindMemory")
@ -479,8 +491,7 @@ def emit_impl(typeInfo, api, cgen):
if api.name in specialCaseDependencyExtractors:
specialCaseDependencyExtractors[api.name](p, boxed_access, lenExpr, api, cgen)
cgen.stmt("auto apiCallHandle = apiCallInfo->handle")
cgen.stmt("mReconstruction.setApiTrace(apiCallInfo, apiCallPacket, apiCallPacketSize)")
cgen.stmt("mReconstruction.setApiTrace(apiCallHandle, apiCallPacket, apiCallPacketSize)")
if lenAccessGuard is not None:
cgen.beginIf(lenAccessGuard)
cgen.stmt(f"mReconstruction.forEachHandleAddApi((const uint64_t*){boxed_access}, {lenExpr}, apiCallHandle, {get_target_state(api, p)})")
@ -508,8 +519,7 @@ def emit_impl(typeInfo, api, cgen):
cgen.endIf();
cgen.stmt("uint64_t handle = m_state->newGlobalVkGenericHandle(%s)" % apiActionsTag[api.name])
cgen.stmt("mReconstruction.addHandles((const uint64_t*)(&handle), 1)");
cgen.stmt("auto apiCallHandle = apiCallInfo->handle")
cgen.stmt("mReconstruction.setApiTrace(apiCallInfo, apiCallPacket, apiCallPacketSize)")
cgen.stmt("mReconstruction.setApiTrace(apiCallHandle, apiCallPacket, apiCallPacketSize)")
if api.name in specialCaseDependencyExtractors:
specialCaseDependencyExtractors[api.name](p, None, None, api, cgen)
cgen.stmt(f"mReconstruction.forEachHandleAddApi((const uint64_t*)(&handle), 1, apiCallHandle, {get_target_state(api, p)})")
@ -518,8 +528,7 @@ def emit_impl(typeInfo, api, cgen):
elif is_modify_operation(api, p):
cgen.stmt("std::lock_guard<std::mutex> lock(mReconstructionMutex)")
cgen.line("// %s modify" % p.paramName)
cgen.stmt("auto apiCallHandle = apiCallInfo->handle")
cgen.stmt("mReconstruction.setApiTrace(apiCallInfo, apiCallPacket, apiCallPacketSize)")
cgen.stmt("mReconstruction.setApiTrace(apiCallHandle, apiCallPacket, apiCallPacketSize)")
if lenAccessGuard is not None:
cgen.beginIf(lenAccessGuard)
cgen.beginFor("uint32_t i = 0", "i < %s" % lenExpr, "++i")
@ -569,7 +578,7 @@ class VulkanDecoderSnapshot(VulkanWrapperGenerator):
additionalParams = [ \
makeVulkanTypeSimple(False, "gfxstream::base::BumpPool", 1, "pool"),
makeVulkanTypeSimple(False, "VkSnapshotApiCallInfo", 1, "apiCallInfo"),
makeVulkanTypeSimple(False, "VkSnapshotApiCallHandle", 0, "apiCallHandle"),
makeVulkanTypeSimple(True, "uint8_t", 1, "apiCallPacket"),
makeVulkanTypeSimple(False, "size_t", 0, "apiCallPacketSize"),
]

View file

@ -23,6 +23,8 @@ global_state_prefix = "this->on_"
READ_STREAM = "readStream"
WRITE_STREAM = "vkStream"
SNAPSHOT_API_CALL_HANDLE_VARNAME = "snapshotApiCallHandle"
# Driver workarounds for APIs that don't work well multithreaded
driver_workarounds_global_lock_apis = [
"vkCreatePipelineLayout",
@ -247,7 +249,7 @@ def emit_decode_parameters(typeInfo, api, cgen, globalWrapped=False):
def emit_snapshot_call(api, cgen):
apiForSnapshot = \
api.withCustomReturnType(makeVulkanTypeSimple(False, "void", 0, "void"))
customParamsSnapshot = ["pool", "snapshotApiCallInfo", "nullptr", "0"]
customParamsSnapshot = ["pool", SNAPSHOT_API_CALL_HANDLE_VARNAME, "nullptr", "0"]
retTypeName = api.getRetTypeExpr()
if retTypeName != "void":
retVar = api.getRetVarExpr()
@ -284,7 +286,7 @@ def emit_dispatch_call(api, cgen):
def emit_global_state_wrapped_call(api, cgen, context=False):
customParams = ["pool", "nullptr", "(VkCommandBuffer)(boxed_dispatchHandle)"] + \
customParams = ["pool", SNAPSHOT_API_CALL_HANDLE_VARNAME, "(VkCommandBuffer)(boxed_dispatchHandle)"] + \
list(map(lambda p: p.paramName, api.parameters[1:]))
if context:
customParams += ["context"];
@ -354,7 +356,7 @@ class VulkanSubDecoder(VulkanWrapperGenerator):
"#define CC_UNLIKELY(exp) (__builtin_expect( !!(exp), false ))\n")
self.module.appendImpl(
"size_t subDecode(VulkanMemReadingStream* readStream, VulkanDispatch* vk, VkSnapshotApiCallInfo* snapshotApiCallInfo, void* boxed_dispatchHandle, void* dispatchHandle, VkDeviceSize subDecodeDataSize, const void* pSubDecodeData, const VkDecoderContext& context)\n")
"size_t subDecode(VulkanMemReadingStream* readStream, VulkanDispatch* vk, VkSnapshotApiCallHandle %s, void* boxed_dispatchHandle, void* dispatchHandle, VkDeviceSize subDecodeDataSize, const void* pSubDecodeData, const VkDecoderContext& context)\n" % SNAPSHOT_API_CALL_HANDLE_VARNAME)
self.cgen.beginBlock() # function body

View file

@ -435,6 +435,11 @@ using gfxstream::base::BumpPool;
deepcopyInclude = """
#include "vk_util.h"
"""
deepcopyHostInclude = """
#include "VkUtils.h"
"""
poolIncludeGuest = f"""
#include "goldfish_vk_private_defs.h"
#include "BumpPool.h"
@ -506,7 +511,7 @@ using DlSymFunc = void* (void*, const char*);
decoderSnapshotHeaderIncludes = f"""
#include <memory>
#include "VkSnapshotApiCall.h"
#include "VkSnapshotHandles.h"
#include "gfxstream/HealthMonitor.h"
#include "gfxstream/host/GfxApiLogger.h"
#include "goldfish_vk_private_defs.h"
@ -523,7 +528,7 @@ using DlSymFunc = void* (void*, const char*);
decoderHeaderIncludes = f"""
#include "VkDecoderContext.h"
#include "ProcessResources.h"
#include "gfxstream/host/ProcessResources.h"
#include <memory>
@ -642,7 +647,7 @@ class BumpPool;
extraImpl=commonCerealImplIncludes + reservedMarshalingHostIncludes)
self.addCppModule("common", "goldfish_vk_deepcopy",
extraHeader=poolInclude,
extraImpl=commonCerealImplIncludes + deepcopyInclude)
extraImpl=commonCerealImplIncludes + deepcopyHostInclude)
self.addCppModule("common", "goldfish_vk_dispatch",
extraHeader=dispatchHeaderDefs,
extraImpl=dispatchImplIncludes)