blob: f1275fba0a463d24d26af29ac738fef2feb47847 [file] [edit]
/*
*
* Copyright (C) 2015-2017 Valve Corporation
* Copyright (C) 2015-2017 LunarG, Inc.
* All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Jon Ashburn <jon@lunarg.com>
* Author: Tobin Ehlis <tobin@lunarg.com>
* Author: Peter Lohrmann <peterl@valvesoftware.com>
* Author: Mark Lobodzinski <mark@lunarg.com>
* Author: David Pinedo <david@lunarg.com>
*/
#include <stdbool.h>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <list>
#include "vktrace_vk_vk.h"
#include "vulkan/vulkan.h"
#include "vulkan/vk_layer.h"
#include "vktrace_platform.h"
#include "vk_dispatch_table_helper.h"
#include "vktrace_common.h"
#include "vktrace_lib_helpers.h"
#include "vktrace_lib_trim.h"
#include "vktrace_interconnect.h"
#include "vktrace_filelike.h"
#include "vktrace_trace_packet_utils.h"
#include "vktrace_vk_exts.h"
#include <stdio.h>
#include "vktrace_pageguard_memorycopy.h"
#include "vktrace_lib_pagestatusarray.h"
#include "vktrace_lib_pageguardmappedmemory.h"
#include "vktrace_lib_pageguardcapture.h"
#include "vktrace_lib_pageguard.h"
// Intentionally include the struct_size source file
#include "vk_struct_size_helper.c"
VKTRACER_LEAVE _Unload(void) {
// only do the hooking and networking if the tracer is NOT loaded by vktrace
if (vktrace_is_loaded_into_vktrace() == FALSE) {
if (vktrace_trace_get_trace_file() != NULL) {
vktrace_trace_packet_header *pHeader =
vktrace_create_trace_packet(VKTRACE_TID_VULKAN, VKTRACE_TPI_MARKER_TERMINATE_PROCESS, 0, 0);
vktrace_finalize_trace_packet(pHeader);
vktrace_write_trace_packet(pHeader, vktrace_trace_get_trace_file());
vktrace_delete_trace_packet(&pHeader);
vktrace_free(vktrace_trace_get_trace_file());
vktrace_trace_set_trace_file(NULL);
vktrace_deinitialize_trace_packet_utils();
trim::deinitialize();
}
if (gMessageStream != NULL) {
vktrace_MessageStream_destroy(&gMessageStream);
}
vktrace_LogVerbose("vktrace_lib library unloaded from PID %d", vktrace_get_pid());
}
}
// declared as extern in vktrace_lib_helpers.h
VKTRACE_CRITICAL_SECTION g_memInfoLock;
VKMemInfo g_memInfo = {0, NULL, NULL, 0};
std::unordered_map<void*, layer_device_data*> g_deviceDataMap;
std::unordered_map<void*, layer_instance_data*> g_instanceDataMap;
layer_instance_data* mid(void* object) {
dispatch_key key = get_dispatch_key(object);
std::unordered_map<void*, layer_instance_data*>::const_iterator got;
got = g_instanceDataMap.find(key);
assert(got != g_instanceDataMap.end());
return got->second;
}
layer_device_data* mdd(void* object) {
dispatch_key key = get_dispatch_key(object);
std::unordered_map<void*, layer_device_data*>::const_iterator got;
got = g_deviceDataMap.find(key);
assert(got != g_deviceDataMap.end());
return got->second;
}
static layer_instance_data* initInstanceData(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa,
std::unordered_map<void*, layer_instance_data*>& map) {
layer_instance_data* pTable;
assert(instance);
dispatch_key key = get_dispatch_key(instance);
std::unordered_map<void*, layer_instance_data*>::const_iterator it = map.find(key);
if (it == map.end()) {
pTable = new layer_instance_data();
map[key] = pTable;
} else {
return it->second;
}
// TODO: Convert to new init method
layer_init_instance_dispatch_table(instance, &pTable->instTable, gpa);
return pTable;
}
static layer_device_data* initDeviceData(VkDevice device, const PFN_vkGetDeviceProcAddr gpa,
std::unordered_map<void*, layer_device_data*>& map) {
layer_device_data* pTable;
dispatch_key key = get_dispatch_key(device);
std::unordered_map<void*, layer_device_data*>::const_iterator it = map.find(key);
if (it == map.end()) {
pTable = new layer_device_data();
map[key] = pTable;
} else {
return it->second;
}
layer_init_device_dispatch_table(device, &pTable->devTable, gpa);
return pTable;
}
/*
* This function will return the pNext pointer of any
* CreateInfo extensions that are not loader extensions.
* This is used to skip past the loader extensions prepended
* to the list during CreateInstance and CreateDevice.
*/
void* strip_create_extensions(const void* pNext) {
VkLayerInstanceCreateInfo* create_info = (VkLayerInstanceCreateInfo*)pNext;
while (create_info && (create_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
create_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)) {
create_info = (VkLayerInstanceCreateInfo*)create_info->pNext;
}
return create_info;
}
#if defined(PLATFORM_LINUX)
// Function to call mprotect and check for errors.
// Returns 0 on success, -1 on failure.
static int32_t mprotectWithErrorCheck(void* addr, size_t size, int prot) {
while (0 != mprotect(addr, size, prot)) {
if (errno == EAGAIN) continue;
// Something bad happened, and it's fatal.
return -1;
}
return 0;
}
// When quering dirty pages from /proc/self/pagemap, there is a
// small window between the reading of this file and when the dirty bits
// are cleared in which some other thread might modify mapped memory.
// We trap these memory writes by setting mapped memory pages to read-only and
// setting the signal handler for SIGSEGV. The signal handler writes the
// addresses that caused a SIGSEGV to a pipe, which are read and handled
// by getMappedDirtyPagesLinux.
// Note that we call mprotect(2) and write(2) in this signal handler.
// Calling mprotect(2) in a signal hander is not POSIX compliant, but
// is known to work on Linux. Calling write(2) in a signal hander is
// allowed by POSIX.
static int pipefd[2];
static void segvHandler(int sig, siginfo_t* si, void* ununsed) {
size_t pageSize = pageguardGetSystemPageSize();
void* addr;
addr = si->si_addr;
if (sizeof(addr) != write(pipefd[1], &addr, sizeof(addr))) {
// Write to pipe failed. This could happen if the app generates 8k SIGSEGV exceptions and the pipe overflows. We'll just
// abort in that case.
abort();
}
// Change the protection of this page to allow the write to proceed.
if (mprotectWithErrorCheck((void*)((uint64_t)si->si_addr & ~(pageSize - 1)), pageSize, PROT_READ | PROT_WRITE) != 0) {
// If the mprotect failed, write addr to the pipe a second time. getMappedDirtyPagesLinux will read consective identical
// values from the pipe and generate an error.
if (sizeof(addr) != write(pipefd[1], &addr, sizeof(addr))) abort();
}
}
// This function is called when we need to update our list of mapped memory
// that is dirty. On Linux, we use the /proc/self/pagemap to detect which pages
// changed. But we also use mprotect with a signal handler for the rare case
// in which mapped memory is written to between when we read the dirty bits
// from /proc/self/pagemap dirty and clear the dirty bits.
void getMappedDirtyPagesLinux(void) {
LPPageGuardMappedMemory pMappedMem;
PBYTE addr, alignedAddrStart, alignedAddrEnd, previousAddr;
uint64_t nPages;
VkDeviceMemory mappedMemory;
off_t pmOffset;
int64_t index;
size_t pageSize = pageguardGetSystemPageSize();
size_t readLen;
VKAllocInfo* pEntry;
struct sigaction sigAction;
static int pmFd = -1;
static std::vector<uint64_t> pageEntries;
// If pageguard isn't enabled, we don't need to do anythhing
if (!getPageGuardEnableFlag()) return;
vktrace_enter_critical_section(&g_memInfoLock);
// Open pagefile, open the pipe, and set a SIGSEGV handler
if (pmFd == -1) {
pmFd = open("/proc/self/pagemap", O_RDONLY);
if (pmFd < 0) VKTRACE_FATAL_ERROR("Failed to open pagemap file. Is your kernel configured with CONFIG_MEM_SOFT_DIRTY?");
if (0 != pipe2(pipefd, O_NONBLOCK)) VKTRACE_FATAL_ERROR("Failed to create pipe.");
// Set the SIGSEGV signal handler
sigAction.sa_sigaction = segvHandler;
sigfillset(&sigAction.sa_mask);
sigAction.sa_flags = SA_SIGINFO;
if (0 != sigaction(SIGSEGV, &sigAction, NULL)) VKTRACE_FATAL_ERROR("sigaction sys call failed.");
}
// Iterate through all mapped memory allocations.
// Check dirty bits of each page in each mapped memory allocation.
for (std::unordered_map<VkDeviceMemory, PageGuardMappedMemory>::iterator it =
getPageGuardControlInstance().getMapMemory().begin();
it != getPageGuardControlInstance().getMapMemory().end(); it++) {
pMappedMem = &(it->second);
mappedMemory = pMappedMem->getMappedMemory();
pEntry = find_mem_info_entry(mappedMemory);
addr = pEntry->pData;
if (!addr) continue;
alignedAddrStart = (PBYTE)((uint64_t)addr & ~(pageSize - 1));
alignedAddrEnd = (PBYTE)(((uint64_t)addr + pEntry->rangeSize + pageSize - 1) & ~(pageSize - 1));
nPages = (alignedAddrEnd - alignedAddrStart) / pageSize;
// Make pages in this memory allocation non-writable so we get a SIGSEGV
// if some other thread writes to this memory while we are examining
// and clearing its dirty bit.
mprotectWithErrorCheck(alignedAddrStart, (size_t)(alignedAddrEnd - alignedAddrStart), PROT_READ);
// Read all the pagemap entries for this mapped memory allocation
if (pageEntries.size() < nPages) pageEntries.resize(nPages);
pmOffset = (off_t)((uint64_t)alignedAddrStart / (uint64_t)pageSize) * 8;
lseek(pmFd, pmOffset, SEEK_SET);
readLen = read(pmFd, &pageEntries[0], 8 * nPages);
assert(readLen == 8 * nPages);
if (readLen != 8 * nPages) VKTRACE_FATAL_ERROR("Failed to read from pagemap file.");
// Examine the dirty bits in each pagemap entry
addr = alignedAddrStart;
for (uint64_t i = 0; i < nPages; i++) {
if ((pageEntries[i] & PTE_DIRTY_BIT) != 0) {
index = pMappedMem->getIndexOfChangedBlockByAddr(addr);
if (index >= 0) {
// If the page is not already marked changed, compute a
// checksum.
// Mark the page as changed if the new checksum doesn't
// match the
// saved checksum, and save the new checksum.
if (!pMappedMem->isMappedBlockChanged(index, BLOCK_FLAG_ARRAY_CHANGED)) {
uint64_t checksum = pMappedMem->computePageChecksum(addr);
if (checksum != pMappedMem->getPageChecksum(index)) {
pMappedMem->setMappedBlockChanged(index, true, BLOCK_FLAG_ARRAY_CHANGED);
pMappedMem->setPageChecksum(index, checksum);
}
}
}
}
addr += pageSize;
}
}
// Clear all dirty bits for this process
#if !defined(ANDROID)
getPageGuardControlInstance().pageRefsDirtyClear();
#endif
// Re-enable write permission for all mapped memory
for (std::unordered_map<VkDeviceMemory, PageGuardMappedMemory>::iterator it =
getPageGuardControlInstance().getMapMemory().begin();
it != getPageGuardControlInstance().getMapMemory().end(); it++) {
pMappedMem = &(it->second);
mappedMemory = pMappedMem->getMappedMemory();
pEntry = find_mem_info_entry(mappedMemory);
addr = pEntry->pData;
if (!addr) continue;
alignedAddrStart = (PBYTE)((uint64_t)addr & ~(pageSize - 1));
alignedAddrEnd = (PBYTE)(((uint64_t)addr + pEntry->rangeSize + pageSize - 1) & ~(pageSize - 1));
mprotectWithErrorCheck(alignedAddrStart, (size_t)(alignedAddrEnd - alignedAddrStart), PROT_READ | PROT_WRITE);
}
// Read all the addresses that caused a segv and mark those pages dirty
previousAddr = 0;
while ((sizeof(addr) == read(pipefd[0], &addr, sizeof(addr)))) {
// If we get consecutive identical addresses, the sig handler is getting called repeatedly with the same address, the
// mprotect call in the sig handler failed, or the app is writing to the same address from different threads. Generate an
// error and exit.
if (previousAddr == addr) {
VKTRACE_FATAL_ERROR("vktrace layer trapped SIGSEGV but unable to handle.");
}
previousAddr = addr;
for (std::unordered_map<VkDeviceMemory, PageGuardMappedMemory>::iterator it =
getPageGuardControlInstance().getMapMemory().begin();
it != getPageGuardControlInstance().getMapMemory().end(); it++) {
pMappedMem = &(it->second);
index = pMappedMem->getIndexOfChangedBlockByAddr(addr);
if (index >= 0) {
// Mark block as changed, and set checksum to invalid.
// We have to set the checksum to invalid because the block
// may be changed by another thread in this process, so
// the checksum we compute would be incorrect. We
// can only compute checksums while memory is mprotect'ed.
pMappedMem->setMappedBlockChanged(index, true, BLOCK_FLAG_ARRAY_CHANGED);
pMappedMem->setPageChecksum(index, PageGuardMappedMemory::CHECKSUM_INVALID);
break;
} else {
// We can't give an error here if we didn't find the address
// in mapped memory. The arrival of a signal might be delayed
// due to process scheduling, and thus might arrive after the
// mapped memory has been unmapped.
}
}
}
vktrace_leave_critical_section(&g_memInfoLock);
}
#endif
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo,
const VkAllocationCallbacks* pAllocator,
VkDeviceMemory* pMemory) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkAllocateMemory* pPacket = NULL;
size_t packetSize = get_struct_chain_size((void*)pAllocateInfo) + sizeof(VkAllocationCallbacks) + sizeof(VkDeviceMemory) * 2;
CREATE_TRACE_PACKET(vkAllocateMemory, packetSize);
result = mdd(device)->devTable.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkAllocateMemory(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocateInfo), sizeof(VkMemoryAllocateInfo), pAllocateInfo);
add_alloc_memory_to_trace_packet(pHeader, (void**)&(pPacket->pAllocateInfo->pNext), pAllocateInfo->pNext);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pMemory), sizeof(VkDeviceMemory), pMemory);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pMemory));
*((VkDeviceMemory*)((PBYTE)pHeader + pHeader->size - (sizeof(VkDeviceMemory)))) = *pMemory;
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_DeviceMemory_object(*pMemory);
info.belongsToDevice = device;
info.ObjectInfo.DeviceMemory.pCreatePacket = trim::copy_packet(pHeader);
info.ObjectInfo.DeviceMemory.memoryTypeIndex = pAllocateInfo->memoryTypeIndex;
info.ObjectInfo.DeviceMemory.propertyFlags = trim::LookUpMemoryProperties(device, pAllocateInfo->memoryTypeIndex);
info.ObjectInfo.DeviceMemory.size = pAllocateInfo->allocationSize;
if (pAllocator != NULL) {
info.ObjectInfo.DeviceMemory.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
// begin custom code
add_new_handle_to_mem_info(*pMemory, pAllocateInfo->allocationSize, NULL);
// end custom code
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset,
VkDeviceSize size, VkFlags flags, void** ppData) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkMapMemory* pPacket = NULL;
VKAllocInfo* entry;
CREATE_TRACE_PACKET(vkMapMemory, sizeof(void*));
result = mdd(device)->devTable.MapMemory(device, memory, offset, size, flags, ppData);
vktrace_set_packet_entrypoint_end_time(pHeader);
entry = find_mem_info_entry(memory);
// For vktrace usage, clamp the memory size to the total size less offset if VK_WHOLE_SIZE is specified.
if (size == VK_WHOLE_SIZE) {
size = entry->totalSize - offset;
}
#ifdef USE_PAGEGUARD_SPEEDUP
pageguardEnter();
getPageGuardControlInstance().vkMapMemoryPageGuardHandle(device, memory, offset, size, flags, ppData);
pageguardExit();
#endif
pPacket = interpret_body_as_vkMapMemory(pHeader);
pPacket->device = device;
pPacket->memory = memory;
pPacket->offset = offset;
pPacket->size = size;
pPacket->flags = flags;
if (ppData != NULL) {
// here we add data(type is void*) pointed by ppData to trace_packet, and put its address to pPacket->ppData
// after adding to trace_packet.
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->ppData), sizeof(void*), ppData);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->ppData));
add_data_to_mem_info(memory, size, offset, *ppData);
}
pPacket->result = result;
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo* pInfo = trim::get_DeviceMemory_objectInfo(memory);
if (pInfo != NULL) {
pInfo->ObjectInfo.DeviceMemory.mappedOffset = offset;
pInfo->ObjectInfo.DeviceMemory.mappedSize = size;
pInfo->ObjectInfo.DeviceMemory.mappedAddress = *ppData;
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkUnmapMemory(VkDevice device, VkDeviceMemory memory) {
vktrace_trace_packet_header* pHeader;
packet_vkUnmapMemory* pPacket;
VKAllocInfo* entry;
size_t siz = 0;
#ifdef USE_PAGEGUARD_SPEEDUP
void* PageGuardMappedData = NULL;
pageguardEnter();
#if defined(PLATFORM_LINUX)
getMappedDirtyPagesLinux();
#endif
getPageGuardControlInstance().vkUnmapMemoryPageGuardHandle(device, memory, &PageGuardMappedData,
&vkFlushMappedMemoryRangesWithoutAPICall);
#endif
uint64_t trace_begin_time = vktrace_get_time();
// insert into packet the data that was written by CPU between the vkMapMemory call and here
// Note must do this prior to the real vkUnMap() or else may get a FAULT
vktrace_enter_critical_section(&g_memInfoLock);
entry = find_mem_info_entry(memory);
if (entry && entry->pData != NULL) {
if (!entry->didFlush) {
// no FlushMapped Memory
siz = (size_t)entry->rangeSize;
}
}
// some title is not 4 byte aligned when call vkMapMemory, so we need
// ROUNDUP_TO_4 to avoid access invalid memory
CREATE_TRACE_PACKET(vkUnmapMemory, ROUNDUP_TO_4(siz));
pHeader->vktrace_begin_time = trace_begin_time;
pPacket = interpret_body_as_vkUnmapMemory(pHeader);
if (siz) {
assert(entry->handle == memory);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pData), siz, entry->pData);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pData));
}
entry->pData = NULL;
vktrace_leave_critical_section(&g_memInfoLock);
pHeader->entrypoint_begin_time = vktrace_get_time();
mdd(device)->devTable.UnmapMemory(device, memory);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket->device = device;
pPacket->memory = memory;
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo* pInfo = trim::get_DeviceMemory_objectInfo(memory);
if (pInfo != NULL) {
pInfo->ObjectInfo.DeviceMemory.mappedOffset = 0;
pInfo->ObjectInfo.DeviceMemory.mappedSize = 0;
pInfo->ObjectInfo.DeviceMemory.mappedAddress = NULL;
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
#ifdef USE_PAGEGUARD_SPEEDUP
if (PageGuardMappedData != nullptr) {
pageguardFreeMemory(PageGuardMappedData);
}
pageguardExit();
#endif
}
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkFreeMemory(VkDevice device, VkDeviceMemory memory,
const VkAllocationCallbacks* pAllocator) {
vktrace_trace_packet_header* pHeader;
packet_vkFreeMemory* pPacket = NULL;
#ifdef USE_PAGEGUARD_SPEEDUP
// There are some apps call vkFreeMemory without call vkUnmapMemory on
// same memory object. in that situation, capture/playback run into error.
// so add process here for that situation.
pageguardEnter();
if (getPageGuardControlInstance().findMappedMemoryObject(device, memory) != nullptr) {
void* PageGuardMappedData = nullptr;
#if defined(PLATFORM_LINUX)
getMappedDirtyPagesLinux();
#endif
getPageGuardControlInstance().vkUnmapMemoryPageGuardHandle(device, memory, &PageGuardMappedData,
&vkFlushMappedMemoryRangesWithoutAPICall);
if (PageGuardMappedData != nullptr) {
pageguardFreeMemory(PageGuardMappedData);
}
}
pageguardExit();
#endif
CREATE_TRACE_PACKET(vkFreeMemory, sizeof(VkAllocationCallbacks));
mdd(device)->devTable.FreeMemory(device, memory, pAllocator);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkFreeMemory(pHeader);
pPacket->device = device;
pPacket->memory = memory;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::remove_DeviceMemory_object(memory);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
// begin custom code
rm_handle_from_mem_info(memory);
// end custom code
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
const VkMappedMemoryRange* pMemoryRanges) {
vktrace_trace_packet_header* pHeader;
VkResult result;
size_t rangesSize = 0;
size_t dataSize = 0;
uint32_t iter;
packet_vkInvalidateMappedMemoryRanges* pPacket = NULL;
uint64_t trace_begin_time = vktrace_get_time();
#ifdef USE_PAGEGUARD_SPEEDUP
pageguardEnter();
resetAllReadFlagAndPageGuard();
#endif
// find out how much memory is in the ranges
for (iter = 0; iter < memoryRangeCount; iter++) {
VkMappedMemoryRange* pRange = (VkMappedMemoryRange*)&pMemoryRanges[iter];
rangesSize += vk_size_vkmappedmemoryrange(pRange);
dataSize += (size_t)pRange->size;
}
CREATE_TRACE_PACKET(vkInvalidateMappedMemoryRanges, rangesSize + sizeof(void*) * memoryRangeCount + dataSize);
pHeader->vktrace_begin_time = trace_begin_time;
pPacket = interpret_body_as_vkInvalidateMappedMemoryRanges(pHeader);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pMemoryRanges), rangesSize, pMemoryRanges);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pMemoryRanges));
// insert into packet the data that was written by CPU between the vkMapMemory call and here
// create a temporary local ppData array and add it to the packet (to reserve the space for the array)
void** ppTmpData = (void**)malloc(memoryRangeCount * sizeof(void*));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->ppData), sizeof(void*) * memoryRangeCount, ppTmpData);
free(ppTmpData);
// now the actual memory
vktrace_enter_critical_section(&g_memInfoLock);
for (iter = 0; iter < memoryRangeCount; iter++) {
VkMappedMemoryRange* pRange = (VkMappedMemoryRange*)&pMemoryRanges[iter];
VKAllocInfo* pEntry = find_mem_info_entry(pRange->memory);
if (pEntry != NULL) {
assert(pEntry->handle == pRange->memory);
assert(pEntry->totalSize >= (pRange->size + pRange->offset));
assert(pEntry->totalSize >= pRange->size);
assert(pRange->offset >= pEntry->rangeOffset &&
(pRange->offset + pRange->size) <= (pEntry->rangeOffset + pEntry->rangeSize));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->ppData[iter]), pRange->size,
pEntry->pData + pRange->offset);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->ppData[iter]));
pEntry->didFlush = TRUE; // Do we need didInvalidate?
} else {
vktrace_LogError("Failed to copy app memory into trace packet (idx = %u) on vkInvalidateMappedMemoryRanges",
pHeader->global_packet_index);
}
}
vktrace_leave_critical_section(&g_memInfoLock);
// now finalize the ppData array since it is done being updated
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->ppData));
pHeader->entrypoint_begin_time = vktrace_get_time();
result = mdd(device)->devTable.InvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket->device = device;
pPacket->memoryRangeCount = memoryRangeCount;
pPacket->result = result;
if (g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
#ifdef USE_PAGEGUARD_SPEEDUP
pageguardExit();
#endif
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
const VkMappedMemoryRange* pMemoryRanges) {
VkResult result;
vktrace_trace_packet_header* pHeader;
size_t rangesSize = 0;
size_t dataSize = 0;
uint32_t iter;
packet_vkFlushMappedMemoryRanges* pPacket = NULL;
#ifdef USE_PAGEGUARD_SPEEDUP
pageguardEnter();
#if defined(PLATFORM_LINUX)
getMappedDirtyPagesLinux();
#endif
PBYTE* ppPackageData = new PBYTE[memoryRangeCount];
getPageGuardControlInstance().vkFlushMappedMemoryRangesPageGuardHandle(
device, memoryRangeCount, pMemoryRanges, ppPackageData); // the packet is not needed if no any change on data of all ranges
#endif
uint64_t trace_begin_time = vktrace_get_time();
// find out how much memory is in the ranges
#ifndef USE_PAGEGUARD_SPEEDUP
for (iter = 0; iter < memoryRangeCount; iter++) {
VkMappedMemoryRange* pRange = (VkMappedMemoryRange*)&pMemoryRanges[iter];
dataSize += ROUNDUP_TO_4(((size_t)(getPageGuardControlInstance().getMappedMemorySize(device, pRange->memory));
}
#else
dataSize = getPageGuardControlInstance().getALLChangedPackageSizeInMappedMemory(device, memoryRangeCount, pMemoryRanges,
ppPackageData);
#endif
rangesSize = sizeof(VkMappedMemoryRange) * memoryRangeCount;
CREATE_TRACE_PACKET(vkFlushMappedMemoryRanges, rangesSize + sizeof(void*) * memoryRangeCount + dataSize);
pHeader->vktrace_begin_time = trace_begin_time;
pPacket = interpret_body_as_vkFlushMappedMemoryRanges(pHeader);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pMemoryRanges), rangesSize, pMemoryRanges);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pMemoryRanges));
// insert into packet the data that was written by CPU between the vkMapMemory call and here
// create a temporary local ppData array and add it to the packet (to reserve the space for the array)
void** ppTmpData = (void**)malloc(memoryRangeCount * sizeof(void*));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->ppData), sizeof(void*) * memoryRangeCount, ppTmpData);
free(ppTmpData);
// now the actual memory
vktrace_enter_critical_section(&g_memInfoLock);
for (iter = 0; iter < memoryRangeCount; iter++) {
VkMappedMemoryRange* pRange = (VkMappedMemoryRange*)&pMemoryRanges[iter];
VKAllocInfo* pEntry = find_mem_info_entry(pRange->memory);
if (pEntry != NULL) {
#if PLATFORM_LINUX
VkDeviceSize rangeSize __attribute__((unused));
#else
VkDeviceSize rangeSize;
#endif
if (pRange->size == VK_WHOLE_SIZE) {
LPPageGuardMappedMemory pOPTMemoryTemp = getPageGuardControlInstance().findMappedMemoryObject(device, pRange);
rangeSize = getPageGuardControlInstance().getMappedMemorySize(device, pRange->memory) -
(pRange->offset - pOPTMemoryTemp->getMappedOffset());
} else
rangeSize = pRange->size;
assert(pEntry->handle == pRange->memory);
assert(pEntry->totalSize >= (rangeSize + pRange->offset));
assert(pEntry->totalSize >= rangeSize);
assert(pRange->offset >= pEntry->rangeOffset &&
(pRange->offset + rangeSize) <= (pEntry->rangeOffset + pEntry->rangeSize));
#ifdef USE_PAGEGUARD_SPEEDUP
LPPageGuardMappedMemory pOPTMemoryTemp = getPageGuardControlInstance().findMappedMemoryObject(device, pRange);
VkDeviceSize OPTPackageSizeTemp = 0;
if (pOPTMemoryTemp) {
PBYTE pOPTDataTemp = pOPTMemoryTemp->getChangedDataPackage(&OPTPackageSizeTemp);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->ppData[iter]), ROUNDUP_TO_4(OPTPackageSizeTemp),
pOPTDataTemp);
pOPTMemoryTemp->clearChangedDataPackage();
pOPTMemoryTemp->resetMemoryObjectAllChangedFlagAndPageGuard();
} else {
PBYTE pOPTDataTemp =
getPageGuardControlInstance().getChangedDataPackageOutOfMap(ppPackageData, iter, &OPTPackageSizeTemp);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->ppData[iter]), ROUNDUP_TO_4(OPTPackageSizeTemp),
pOPTDataTemp);
getPageGuardControlInstance().clearChangedDataPackageOutOfMap(ppPackageData, iter);
}
#else
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->ppData[iter]), ROUNDUP_TO_4(rangeSize),
pEntry->pData + pRange->offset);
#endif
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->ppData[iter]));
pEntry->didFlush = TRUE;
} else {
vktrace_LogError("Failed to copy app memory into trace packet (idx = %u) on vkFlushedMappedMemoryRanges",
pHeader->global_packet_index);
}
}
#ifdef USE_PAGEGUARD_SPEEDUP
delete[] ppPackageData;
#endif
vktrace_leave_critical_section(&g_memInfoLock);
// now finalize the ppData array since it is done being updated
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->ppData));
pHeader->entrypoint_begin_time = vktrace_get_time();
result = mdd(device)->devTable.FlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket->device = device;
pPacket->memoryRangeCount = memoryRangeCount;
pPacket->result = result;
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
// Currently tracing the frame, so need to track references & store packet to write post-tracing.
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
#ifdef USE_PAGEGUARD_SPEEDUP
pageguardExit();
#endif
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkAllocateCommandBuffers(VkDevice device,
const VkCommandBufferAllocateInfo* pAllocateInfo,
VkCommandBuffer* pCommandBuffers) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkAllocateCommandBuffers* pPacket = NULL;
CREATE_TRACE_PACKET(vkAllocateCommandBuffers,
get_struct_chain_size((void*)pAllocateInfo) + sizeof(VkCommandBuffer) * pAllocateInfo->commandBufferCount);
result = mdd(device)->devTable.AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkAllocateCommandBuffers(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocateInfo), sizeof(VkCommandBufferAllocateInfo),
pAllocateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCommandBuffers),
sizeof(VkCommandBuffer) * pAllocateInfo->commandBufferCount, pCommandBuffers);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCommandBuffers));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo* pPoolInfo = trim::get_CommandPool_objectInfo(pAllocateInfo->commandPool);
if (pPoolInfo != NULL) {
pPoolInfo->ObjectInfo.CommandPool.numCommandBuffersAllocated[pAllocateInfo->level] += pAllocateInfo->commandBufferCount;
}
for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) {
trim::ObjectInfo& info = trim::add_CommandBuffer_object(pCommandBuffers[i]);
info.belongsToDevice = device;
info.ObjectInfo.CommandBuffer.commandPool = pAllocateInfo->commandPool;
info.ObjectInfo.CommandBuffer.level = pAllocateInfo->level;
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkBeginCommandBuffer(VkCommandBuffer commandBuffer,
const VkCommandBufferBeginInfo* pBeginInfo) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkBeginCommandBuffer* pPacket = NULL;
CREATE_TRACE_PACKET(vkBeginCommandBuffer, get_struct_chain_size((void*)pBeginInfo));
result = mdd(commandBuffer)->devTable.BeginCommandBuffer(commandBuffer, pBeginInfo);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkBeginCommandBuffer(pHeader);
pPacket->commandBuffer = commandBuffer;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBeginInfo), sizeof(VkCommandBufferBeginInfo), pBeginInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBeginInfo->pInheritanceInfo),
sizeof(VkCommandBufferInheritanceInfo), pBeginInfo->pInheritanceInfo);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBeginInfo->pInheritanceInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBeginInfo));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::remove_CommandBuffer_calls(commandBuffer);
trim::add_CommandBuffer_call(commandBuffer, trim::copy_packet(pHeader));
trim::ClearImageTransitions(commandBuffer);
trim::ClearBufferTransitions(commandBuffer);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateDescriptorPool(VkDevice device,
const VkDescriptorPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorPool* pDescriptorPool) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateDescriptorPool* pPacket = NULL;
// begin custom code (needs to use get_struct_chain_size)
CREATE_TRACE_PACKET(vkCreateDescriptorPool,
get_struct_chain_size((void*)pCreateInfo) + sizeof(VkAllocationCallbacks) + sizeof(VkDescriptorPool));
// end custom code
result = mdd(device)->devTable.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCreateDescriptorPool(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkDescriptorPoolCreateInfo), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pPoolSizes),
pCreateInfo->poolSizeCount * sizeof(VkDescriptorPoolSize), pCreateInfo->pPoolSizes);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorPool), sizeof(VkDescriptorPool), pDescriptorPool);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pPoolSizes));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorPool));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_DescriptorPool_object(*pDescriptorPool);
info.belongsToDevice = device;
info.ObjectInfo.DescriptorPool.pCreatePacket = trim::copy_packet(pHeader);
info.ObjectInfo.DescriptorPool.createFlags = pCreateInfo->flags;
info.ObjectInfo.DescriptorPool.maxSets = pCreateInfo->maxSets;
info.ObjectInfo.DescriptorPool.numSets = 0;
if (pAllocator != NULL) {
info.ObjectInfo.DescriptorPool.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VkLayerDeviceCreateInfo* get_chain_info(const VkDeviceCreateInfo* pCreateInfo, VkLayerFunction func) {
VkLayerDeviceCreateInfo* chain_info = (VkLayerDeviceCreateInfo*)pCreateInfo->pNext;
while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
chain_info = (VkLayerDeviceCreateInfo*)chain_info->pNext;
}
assert(chain_info != NULL);
return chain_info;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateDevice(VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
vktrace_trace_packet_header* pHeader;
VkResult result;
packet_vkCreateDevice* pPacket = NULL;
VkLayerDeviceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
assert(chain_info->u.pLayerInfo);
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
assert(fpGetInstanceProcAddr);
PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
assert(fpGetDeviceProcAddr);
PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
if (fpCreateDevice == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
// Advance the link info for the next element on the chain
chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
if (result != VK_SUCCESS) {
return result;
}
initDeviceData(*pDevice, fpGetDeviceProcAddr, g_deviceDataMap);
// Setup device dispatch table for extensions
ext_init_create_device(mdd(*pDevice), *pDevice, fpGetDeviceProcAddr, pCreateInfo->enabledExtensionCount,
pCreateInfo->ppEnabledExtensionNames);
// remove the loader extended createInfo structure
VkDeviceCreateInfo localCreateInfo;
memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo));
localCreateInfo.pNext = strip_create_extensions(pCreateInfo->pNext);
CREATE_TRACE_PACKET(vkCreateDevice,
get_struct_chain_size((void*)&localCreateInfo) + sizeof(VkAllocationCallbacks) + sizeof(VkDevice));
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCreateDevice(pHeader);
pPacket->physicalDevice = physicalDevice;
add_VkDeviceCreateInfo_to_packet(pHeader, (VkDeviceCreateInfo**)&(pPacket->pCreateInfo), &localCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDevice), sizeof(VkDevice), pDevice);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDevice));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_Device_object(*pDevice);
info.belongsToPhysicalDevice = physicalDevice;
info.ObjectInfo.Device.pCreatePacket = trim::copy_packet(pHeader);
trim::ObjectInfo* pPhysDevInfo = trim::get_PhysicalDevice_objectInfo(physicalDevice);
if (pPhysDevInfo != nullptr) {
info.ObjectInfo.Device.queueFamilyCount = pPhysDevInfo->ObjectInfo.PhysicalDevice.queueFamilyCount;
info.ObjectInfo.Device.pQueueFamilies = VKTRACE_NEW_ARRAY(trim::QueueFamily, info.ObjectInfo.Device.queueFamilyCount);
for (uint32_t family = 0; family < info.ObjectInfo.Device.queueFamilyCount; family++) {
info.ObjectInfo.Device.pQueueFamilies[family].count = 0;
info.ObjectInfo.Device.pQueueFamilies[family].queues = nullptr;
}
for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
uint32_t queueFamilyIndex = pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex;
uint32_t count = pCreateInfo->pQueueCreateInfos[i].queueCount;
info.ObjectInfo.Device.pQueueFamilies[queueFamilyIndex].count = count;
info.ObjectInfo.Device.pQueueFamilies[queueFamilyIndex].queues = VKTRACE_NEW_ARRAY(VkQueue, count);
for (uint32_t q = 0; q < count; q++) {
VkQueue queue = VK_NULL_HANDLE;
mdd(*pDevice)->devTable.GetDeviceQueue(*pDevice, queueFamilyIndex, q, &queue);
info.ObjectInfo.Device.pQueueFamilies[queueFamilyIndex].queues[q] = queue;
}
}
}
if (pAllocator != NULL) {
info.ObjectInfo.Device.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateFramebuffer(VkDevice device,
const VkFramebufferCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFramebuffer* pFramebuffer) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateFramebuffer* pPacket = NULL;
// begin custom code
uint32_t attachmentCount = (pCreateInfo != NULL && pCreateInfo->pAttachments != NULL) ? pCreateInfo->attachmentCount : 0;
CREATE_TRACE_PACKET(vkCreateFramebuffer,
get_struct_chain_size((void*)pCreateInfo) + sizeof(VkAllocationCallbacks) + sizeof(VkFramebuffer));
// end custom code
result = mdd(device)->devTable.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCreateFramebuffer(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkFramebufferCreateInfo), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pAttachments),
attachmentCount * sizeof(VkImageView), pCreateInfo->pAttachments);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pFramebuffer), sizeof(VkFramebuffer), pFramebuffer);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pAttachments));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pFramebuffer));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_Framebuffer_object(*pFramebuffer);
info.belongsToDevice = device;
info.ObjectInfo.Framebuffer.pCreatePacket = trim::copy_packet(pHeader);
info.ObjectInfo.Framebuffer.attachmentCount = pCreateInfo->attachmentCount;
if (pCreateInfo->attachmentCount == 0) {
info.ObjectInfo.Framebuffer.pAttachments = nullptr;
} else {
info.ObjectInfo.Framebuffer.pAttachments = new VkImageView[pCreateInfo->attachmentCount];
memcpy(info.ObjectInfo.Framebuffer.pAttachments, pCreateInfo->pAttachments,
sizeof(VkImageView) * pCreateInfo->attachmentCount);
}
if (pAllocator != NULL) {
info.ObjectInfo.Framebuffer.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VkLayerInstanceCreateInfo* get_chain_info(const VkInstanceCreateInfo* pCreateInfo, VkLayerFunction func) {
VkLayerInstanceCreateInfo* chain_info = (VkLayerInstanceCreateInfo*)pCreateInfo->pNext;
while (chain_info && ((chain_info->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO) || (chain_info->function != func))) {
chain_info = (VkLayerInstanceCreateInfo*)chain_info->pNext;
}
assert(chain_info != NULL);
return chain_info;
}
#if defined(USE_PAGEGUARD_SPEEDUP) && !defined(PAGEGUARD_MEMCPY_USE_PPL_LIB)
extern "C" BOOL vktrace_pageguard_init_multi_threads_memcpy();
extern "C" void vktrace_pageguard_done_multi_threads_memcpy();
#endif
static bool send_vk_trace_file_header(VkInstance instance) {
bool rval = false;
uint64_t packet_size;
vktrace_trace_file_header* pHeader;
uint32_t physDevCount;
size_t header_size;
VkPhysicalDevice* pPhysDevice;
VkPhysicalDeviceProperties devProperties;
struct_gpuinfo* pGpuinfo;
// Find out how many physical devices we have
if (VK_SUCCESS != mid(instance)->instTable.EnumeratePhysicalDevices(instance, &physDevCount, NULL) || physDevCount < 1) {
return false;
}
header_size = sizeof(vktrace_trace_file_header) + physDevCount * sizeof(struct_gpuinfo);
packet_size = header_size + sizeof(packet_size);
if (!(pPhysDevice = (VkPhysicalDevice*)vktrace_malloc(header_size + sizeof(VkPhysicalDevice) * physDevCount))) {
return false;
}
pHeader = (vktrace_trace_file_header*)((PBYTE)pPhysDevice + sizeof(VkPhysicalDevice) * physDevCount);
pGpuinfo = (struct_gpuinfo*)((PBYTE)pHeader + sizeof(vktrace_trace_file_header));
// Get information about all physical devices
if (VK_SUCCESS != mid(instance)->instTable.EnumeratePhysicalDevices(instance, &physDevCount, pPhysDevice)) {
goto cleanupAndReturn;
}
memset(pHeader, 0, header_size);
pHeader->trace_file_version = VKTRACE_TRACE_FILE_VERSION;
pHeader->magic = VKTRACE_FILE_MAGIC;
vktrace_gen_uuid(pHeader->uuid);
pHeader->first_packet_offset = header_size;
pHeader->tracer_count = 1;
pHeader->tracer_id_array[0].id = VKTRACE_TID_VULKAN;
pHeader->tracer_id_array[0].is_64_bit = (sizeof(intptr_t) == 8) ? 1 : 0;
pHeader->trace_start_time = vktrace_get_time();
pHeader->endianess = get_endianess();
pHeader->ptrsize = sizeof(void*);
pHeader->arch = get_arch();
pHeader->os = get_os();
pHeader->n_gpuinfo = physDevCount;
for (size_t i = 0; i < physDevCount; i++) {
mid(*(pPhysDevice + i))->instTable.GetPhysicalDeviceProperties(*(pPhysDevice + i), &devProperties);
pGpuinfo[i].gpu_id = ((uint64_t)devProperties.vendorID << 32) | (uint64_t)devProperties.deviceID;
pGpuinfo[i].gpu_drv_vers = (uint64_t)devProperties.driverVersion;
}
vktrace_FileLike_WriteRaw(vktrace_trace_get_trace_file(), &packet_size, sizeof(packet_size));
vktrace_FileLike_WriteRaw(vktrace_trace_get_trace_file(), pHeader, header_size);
rval = true;
cleanupAndReturn:
vktrace_free(pPhysDevice);
return rval;
}
static void send_vk_api_version_packet() {
packet_vkApiVersion* pPacket;
vktrace_trace_packet_header* pHeader;
pHeader = vktrace_create_trace_packet(VKTRACE_TID_VULKAN, VKTRACE_TPI_VK_vkApiVersion, sizeof(packet_vkApiVersion), 0);
pPacket = interpret_body_as_vkApiVersion(pHeader);
pPacket->version = VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION);
vktrace_set_packet_entrypoint_end_time(pHeader);
FINISH_TRACE_PACKET();
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance) {
vktrace_trace_packet_header* pHeader;
VkResult result;
packet_vkCreateInstance* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint32_t i;
uint64_t vktraceStartTime = vktrace_get_time();
SEND_ENTRYPOINT_ID(vkCreateInstance);
startTime = vktrace_get_time();
#if defined(USE_PAGEGUARD_SPEEDUP) && !defined(PAGEGUARD_MEMCPY_USE_PPL_LIB)
vktrace_pageguard_init_multi_threads_memcpy();
#endif
VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
assert(chain_info->u.pLayerInfo);
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
assert(fpGetInstanceProcAddr);
PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
if (fpCreateInstance == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
// Advance the link info for the next element on the chain
chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
if (result != VK_SUCCESS) {
return result;
}
endTime = vktrace_get_time();
initInstanceData(*pInstance, fpGetInstanceProcAddr, g_instanceDataMap);
ext_init_create_instance(mid(*pInstance), *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
// remove the loader extended createInfo structure
VkInstanceCreateInfo localCreateInfo;
memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo));
// Alloc space to copy pointers
if (localCreateInfo.enabledLayerCount > 0)
localCreateInfo.ppEnabledLayerNames = (const char* const*)malloc(localCreateInfo.enabledLayerCount * sizeof(char*));
if (localCreateInfo.enabledExtensionCount > 0)
localCreateInfo.ppEnabledExtensionNames = (const char* const*)malloc(localCreateInfo.enabledExtensionCount * sizeof(char*));
for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
char** ppName = (char**)&localCreateInfo.ppEnabledExtensionNames[i];
*ppName = (char*)pCreateInfo->ppEnabledExtensionNames[i];
}
// If app requests vktrace layer, don't record that in the trace
char** ppName = (char**)&localCreateInfo.ppEnabledLayerNames[0];
for (i = 0; i < pCreateInfo->enabledLayerCount; i++) {
if (strcmp("VK_LAYER_LUNARG_vktrace", pCreateInfo->ppEnabledLayerNames[i]) == 0) {
// Decrement the enabled layer count and skip copying the pointer
localCreateInfo.enabledLayerCount--;
} else {
// Copy pointer and increment write pointer for everything else
*ppName++ = (char*)pCreateInfo->ppEnabledLayerNames[i];
}
}
// If this is the first vkCreateInstance call, we haven't written the file header
// packets to the trace file yet because we need the instance to first be be created
// so we can query information needed for the file header. So write the headers now.
// We can do this because vkCreateInstance must always be the first Vulkan API call.
static bool firstCreateInstance = true;
if (firstCreateInstance) {
if (!send_vk_trace_file_header(*pInstance)) vktrace_LogError("Failed to write trace file header");
send_vk_api_version_packet();
firstCreateInstance = false;
}
// localCreateInfo.pNext = strip_create_extensions(pCreateInfo->pNext);
// The pNext pointer isn't getting marshalled into the trace buffer properly anyway, so
// set it to NULL so that replay does not trip over it.
localCreateInfo.pNext = NULL;
CREATE_TRACE_PACKET(vkCreateInstance,
sizeof(VkInstance) + get_struct_chain_size((void*)&localCreateInfo) + sizeof(VkAllocationCallbacks));
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkCreateInstance(pHeader);
add_VkInstanceCreateInfo_to_packet(pHeader, (VkInstanceCreateInfo**)&(pPacket->pCreateInfo),
(VkInstanceCreateInfo*)&localCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pInstance), sizeof(VkInstance), pInstance);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pInstance));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_Instance_object(*pInstance);
info.ObjectInfo.Instance.pCreatePacket = trim::copy_packet(pHeader);
if (pAllocator != NULL) {
info.ObjectInfo.Instance.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
if (localCreateInfo.enabledLayerCount > 0) free((void*)localCreateInfo.ppEnabledLayerNames);
if (localCreateInfo.enabledExtensionCount > 0) free((void*)localCreateInfo.ppEnabledExtensionNames);
return result;
}
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkDestroyInstance(VkInstance instance,
const VkAllocationCallbacks* pAllocator) {
if (g_trimEnabled && g_trimIsInTrim) {
trim::stop();
}
vktrace_trace_packet_header* pHeader;
packet_vkDestroyInstance* pPacket = NULL;
dispatch_key key = get_dispatch_key(instance);
CREATE_TRACE_PACKET(vkDestroyInstance, sizeof(VkAllocationCallbacks));
mid(instance)->instTable.DestroyInstance(instance, pAllocator);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkDestroyInstance(pHeader);
pPacket->instance = instance;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::remove_Instance_object(instance);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
g_instanceDataMap.erase(key);
#if defined(USE_PAGEGUARD_SPEEDUP) && !defined(PAGEGUARD_MEMCPY_USE_PPL_LIB)
vktrace_pageguard_done_multi_threads_memcpy();
#endif
#if defined(ANDROID)
_Unload();
#endif
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateRenderPass(VkDevice device,
const VkRenderPassCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkRenderPass* pRenderPass) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateRenderPass* pPacket = NULL;
// begin custom code (get_struct_chain_size)
uint32_t attachmentCount = (pCreateInfo != NULL && (pCreateInfo->pAttachments != NULL)) ? pCreateInfo->attachmentCount : 0;
uint32_t dependencyCount = (pCreateInfo != NULL && (pCreateInfo->pDependencies != NULL)) ? pCreateInfo->dependencyCount : 0;
uint32_t subpassCount = (pCreateInfo != NULL && (pCreateInfo->pSubpasses != NULL)) ? pCreateInfo->subpassCount : 0;
CREATE_TRACE_PACKET(vkCreateRenderPass,
get_struct_chain_size((void*)pCreateInfo) + sizeof(VkAllocationCallbacks) + sizeof(VkRenderPass));
// end custom code
result = mdd(device)->devTable.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCreateRenderPass(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkRenderPassCreateInfo), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pAttachments),
attachmentCount * sizeof(VkAttachmentDescription), pCreateInfo->pAttachments);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pDependencies),
dependencyCount * sizeof(VkSubpassDependency), pCreateInfo->pDependencies);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pSubpasses),
subpassCount * sizeof(VkSubpassDescription), pCreateInfo->pSubpasses);
for (uint32_t i = 0; i < pPacket->pCreateInfo->subpassCount; i++) {
VkSubpassDescription* pSubpass = (VkSubpassDescription*)&pPacket->pCreateInfo->pSubpasses[i];
const VkSubpassDescription* pSp = &pCreateInfo->pSubpasses[i];
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pSubpass->pInputAttachments),
pSubpass->inputAttachmentCount * sizeof(VkAttachmentReference), pSp->pInputAttachments);
vktrace_finalize_buffer_address(pHeader, (void**)&(pSubpass->pInputAttachments));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pSubpass->pColorAttachments),
pSubpass->colorAttachmentCount * sizeof(VkAttachmentReference), pSp->pColorAttachments);
vktrace_finalize_buffer_address(pHeader, (void**)&(pSubpass->pColorAttachments));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pSubpass->pResolveAttachments),
pSubpass->colorAttachmentCount * sizeof(VkAttachmentReference),
pSp->pResolveAttachments);
vktrace_finalize_buffer_address(pHeader, (void**)&(pSubpass->pResolveAttachments));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pSubpass->pDepthStencilAttachment), 1 * sizeof(VkAttachmentReference),
pSp->pDepthStencilAttachment);
vktrace_finalize_buffer_address(pHeader, (void**)&(pSubpass->pDepthStencilAttachment));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pSubpass->pPreserveAttachments),
pSubpass->preserveAttachmentCount * sizeof(VkAttachmentReference),
pSp->pPreserveAttachments);
vktrace_finalize_buffer_address(pHeader, (void**)&(pSubpass->pPreserveAttachments));
}
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pRenderPass), sizeof(VkRenderPass), pRenderPass);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pAttachments));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pDependencies));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pSubpasses));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pRenderPass));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_RenderPass_object(*pRenderPass);
trim::add_RenderPassCreateInfo(*pRenderPass, pCreateInfo);
info.belongsToDevice = device;
info.ObjectInfo.RenderPass.pCreatePacket = trim::copy_packet(pHeader);
if (pCreateInfo == nullptr || pCreateInfo->attachmentCount == 0) {
info.ObjectInfo.RenderPass.attachmentCount = 0;
info.ObjectInfo.RenderPass.pAttachments = nullptr;
} else {
info.ObjectInfo.RenderPass.attachmentCount = pCreateInfo->attachmentCount;
info.ObjectInfo.RenderPass.pAttachments = new trim::ImageTransition[pCreateInfo->attachmentCount];
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
info.ObjectInfo.RenderPass.pAttachments[i].initialLayout = pCreateInfo->pAttachments[i].initialLayout;
info.ObjectInfo.RenderPass.pAttachments[i].finalLayout = pCreateInfo->pAttachments[i].finalLayout;
// We don't know which object it is at this time, but we'll find out in VkBindDescriptorSets().
info.ObjectInfo.RenderPass.pAttachments[i].image = VK_NULL_HANDLE;
}
}
if (pAllocator != NULL) {
info.ObjectInfo.RenderPass.pAllocator = pAllocator;
}
if (pAllocator != NULL) {
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkEnumerateDeviceExtensionProperties* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
startTime = vktrace_get_time();
// Only call down chain if querying ICD rather than layer device extensions
if (pLayerName == NULL)
result =
mid(physicalDevice)->instTable.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pPropertyCount, pProperties);
else {
*pPropertyCount = 0;
return VK_SUCCESS;
}
endTime = vktrace_get_time();
CREATE_TRACE_PACKET(vkEnumerateDeviceExtensionProperties, ((pLayerName != NULL) ? ROUNDUP_TO_4(strlen(pLayerName) + 1) : 0) +
sizeof(uint32_t) +
(*pPropertyCount * sizeof(VkExtensionProperties)));
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkEnumerateDeviceExtensionProperties(pHeader);
pPacket->physicalDevice = physicalDevice;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pLayerName),
((pLayerName != NULL) ? ROUNDUP_TO_4(strlen(pLayerName) + 1) : 0), pLayerName);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPropertyCount), sizeof(uint32_t), pPropertyCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pProperties), *pPropertyCount * sizeof(VkExtensionProperties),
pProperties);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pLayerName));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPropertyCount));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pProperties));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
uint32_t* pPropertyCount,
VkLayerProperties* pProperties) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkEnumerateDeviceLayerProperties* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
startTime = vktrace_get_time();
result = mid(physicalDevice)->instTable.EnumerateDeviceLayerProperties(physicalDevice, pPropertyCount, pProperties);
endTime = vktrace_get_time();
CREATE_TRACE_PACKET(vkEnumerateDeviceLayerProperties, sizeof(uint32_t) + (*pPropertyCount * sizeof(VkLayerProperties)));
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkEnumerateDeviceLayerProperties(pHeader);
pPacket->physicalDevice = physicalDevice;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPropertyCount), sizeof(uint32_t), pPropertyCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pProperties), *pPropertyCount * sizeof(VkLayerProperties),
pProperties);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPropertyCount));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pProperties));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
// TODO : This should be pretty easy to fit into codegen. Don't need to make the call prior to creating packet
// Just need to account for "count" number of queue properties
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkGetPhysicalDeviceQueueFamilyProperties(
VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties) {
vktrace_trace_packet_header* pHeader;
packet_vkGetPhysicalDeviceQueueFamilyProperties* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
startTime = vktrace_get_time();
mid(physicalDevice)
->instTable.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
endTime = vktrace_get_time();
CREATE_TRACE_PACKET(vkGetPhysicalDeviceQueueFamilyProperties,
sizeof(uint32_t) + *pQueueFamilyPropertyCount * sizeof(VkQueueFamilyProperties));
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkGetPhysicalDeviceQueueFamilyProperties(pHeader);
pPacket->physicalDevice = physicalDevice;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pQueueFamilyPropertyCount), sizeof(uint32_t),
pQueueFamilyPropertyCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pQueueFamilyProperties),
*pQueueFamilyPropertyCount * sizeof(VkQueueFamilyProperties), pQueueFamilyProperties);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pQueueFamilyPropertyCount));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pQueueFamilyProperties));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo* pInfo = trim::get_PhysicalDevice_objectInfo(physicalDevice);
if (pInfo != NULL) {
if (pQueueFamilyProperties == nullptr) {
pInfo->ObjectInfo.PhysicalDevice.pGetPhysicalDeviceQueueFamilyPropertiesCountPacket = trim::copy_packet(pHeader);
pInfo->ObjectInfo.PhysicalDevice.queueFamilyCount = *pQueueFamilyPropertyCount;
} else {
pInfo->ObjectInfo.PhysicalDevice.pGetPhysicalDeviceQueueFamilyPropertiesPacket = trim::copy_packet(pHeader);
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkEnumeratePhysicalDevices(VkInstance instance,
uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkEnumeratePhysicalDevices* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
// TODO make sure can handle being called twice with pPD == 0
SEND_ENTRYPOINT_ID(vkEnumeratePhysicalDevices);
startTime = vktrace_get_time();
result = mid(instance)->instTable.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
endTime = vktrace_get_time();
CREATE_TRACE_PACKET(
vkEnumeratePhysicalDevices,
sizeof(uint32_t) + ((pPhysicalDevices && pPhysicalDeviceCount) ? *pPhysicalDeviceCount * sizeof(VkPhysicalDevice) : 0));
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkEnumeratePhysicalDevices(pHeader);
pPacket->instance = instance;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPhysicalDeviceCount), sizeof(uint32_t), pPhysicalDeviceCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPhysicalDevices),
*pPhysicalDeviceCount * sizeof(VkPhysicalDevice), pPhysicalDevices);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPhysicalDeviceCount));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPhysicalDevices));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (result == VK_SUCCESS) {
trim::ObjectInfo* pInfo = trim::get_Instance_objectInfo(instance);
if (pInfo != NULL && pPhysicalDeviceCount != NULL && pPhysicalDevices == NULL) {
pInfo->ObjectInfo.Instance.pEnumeratePhysicalDevicesCountPacket = trim::copy_packet(pHeader);
}
if (pPhysicalDevices != NULL && pPhysicalDeviceCount != NULL) {
if (pInfo != NULL) {
pInfo->ObjectInfo.Instance.pEnumeratePhysicalDevicesPacket = trim::copy_packet(pHeader);
}
for (uint32_t iter = 0; iter < *pPhysicalDeviceCount; iter++) {
trim::ObjectInfo& PDInfo = trim::add_PhysicalDevice_object(pPhysicalDevices[iter]);
PDInfo.belongsToInstance = instance;
// Get the memory properties of the device
mid(instance)->instTable.GetPhysicalDeviceMemoryProperties(
pPhysicalDevices[iter], &PDInfo.ObjectInfo.PhysicalDevice.physicalDeviceMemoryProperties);
}
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool,
uint32_t firstQuery, uint32_t queryCount,
size_t dataSize, void* pData, VkDeviceSize stride,
VkQueryResultFlags flags) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkGetQueryPoolResults* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
startTime = vktrace_get_time();
result = mdd(device)->devTable.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
endTime = vktrace_get_time();
CREATE_TRACE_PACKET(vkGetQueryPoolResults, dataSize);
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkGetQueryPoolResults(pHeader);
pPacket->device = device;
pPacket->queryPool = queryPool;
pPacket->firstQuery = firstQuery;
pPacket->queryCount = queryCount;
pPacket->dataSize = dataSize;
pPacket->stride = stride;
pPacket->flags = flags;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pData), dataSize, pData);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pData));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkAllocateDescriptorSets(VkDevice device,
const VkDescriptorSetAllocateInfo* pAllocateInfo,
VkDescriptorSet* pDescriptorSets) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkAllocateDescriptorSets* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
SEND_ENTRYPOINT_ID(vkAllocateDescriptorSets);
startTime = vktrace_get_time();
result = mdd(device)->devTable.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
endTime = vktrace_get_time();
CREATE_TRACE_PACKET(vkAllocateDescriptorSets, vk_size_vkdescriptorsetallocateinfo(pAllocateInfo) +
(pAllocateInfo->descriptorSetCount * sizeof(VkDescriptorSet)));
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkAllocateDescriptorSets(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocateInfo), sizeof(VkDescriptorSetAllocateInfo),
pAllocateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocateInfo->pSetLayouts),
pPacket->pAllocateInfo->descriptorSetCount * sizeof(VkDescriptorSetLayout),
pAllocateInfo->pSetLayouts);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorSets),
pPacket->pAllocateInfo->descriptorSetCount * sizeof(VkDescriptorSet), pDescriptorSets);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocateInfo->pSetLayouts));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorSets));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocateInfo));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo* pPoolInfo = trim::get_DescriptorPool_objectInfo(pAllocateInfo->descriptorPool);
if (pPoolInfo != NULL) {
pPoolInfo->ObjectInfo.DescriptorPool.numSets += pAllocateInfo->descriptorSetCount;
}
for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
trim::ObjectInfo& setInfo = trim::add_DescriptorSet_object(pDescriptorSets[i]);
setInfo.belongsToDevice = device;
setInfo.ObjectInfo.DescriptorSet.descriptorPool = pAllocateInfo->descriptorPool;
setInfo.ObjectInfo.DescriptorSet.layout = pAllocateInfo->pSetLayouts[i];
// need to allocate for a potential write & copy to update the descriptor; one for each binding based on the layout
trim::ObjectInfo* pLayoutInfo = trim::get_DescriptorSetLayout_objectInfo(pAllocateInfo->pSetLayouts[i]);
if (pLayoutInfo != NULL) {
uint32_t numImages = pLayoutInfo->ObjectInfo.DescriptorSetLayout.numImages;
uint32_t numBuffers = pLayoutInfo->ObjectInfo.DescriptorSetLayout.numBuffers;
uint32_t numTexelBufferViews = pLayoutInfo->ObjectInfo.DescriptorSetLayout.numTexelBufferViews;
uint32_t numBindings = numImages + numBuffers + numTexelBufferViews;
setInfo.ObjectInfo.DescriptorSet.numBindings = numBindings;
setInfo.ObjectInfo.DescriptorSet.writeDescriptorCount = 0;
setInfo.ObjectInfo.DescriptorSet.copyDescriptorCount = 0;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets = new VkWriteDescriptorSet[numBindings];
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets = new VkCopyDescriptorSet[numBindings];
// setup these WriteDescriptorSets to be specific to each binding of the associated layout
for (uint32_t b = 0; b < pLayoutInfo->ObjectInfo.DescriptorSetLayout.bindingCount; b++) {
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pNext = NULL;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].dstArrayElement =
0; // defaulting to 0, no way to know for sure at this time
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].dstSet = pDescriptorSets[i];
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].dstBinding =
pLayoutInfo->ObjectInfo.DescriptorSetLayout.pBindings[b].binding;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].descriptorCount =
pLayoutInfo->ObjectInfo.DescriptorSetLayout.pBindings[b].descriptorCount;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].descriptorType =
pLayoutInfo->ObjectInfo.DescriptorSetLayout.pBindings[b].descriptorType;
switch (setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pImageInfo =
new VkDescriptorImageInfo[setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].descriptorCount];
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pBufferInfo = NULL;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pTexelBufferView = NULL;
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pImageInfo = NULL;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pBufferInfo =
new VkDescriptorBufferInfo[setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b]
.descriptorCount];
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pTexelBufferView = NULL;
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pImageInfo = NULL;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pBufferInfo = NULL;
setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].pTexelBufferView =
new VkBufferView[setInfo.ObjectInfo.DescriptorSet.pWriteDescriptorSets[b].descriptorCount];
} break;
default:
break;
}
}
// setup the CopyDescriptorSets similar to above
for (uint32_t b = 0; b < pLayoutInfo->ObjectInfo.DescriptorSetLayout.bindingCount; b++) {
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].pNext = NULL;
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].descriptorCount =
pLayoutInfo->ObjectInfo.DescriptorSetLayout.pBindings[b].descriptorCount;
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].dstArrayElement =
0; // defaulting to 0, no way to know for sure at this time
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].dstSet = pDescriptorSets[i];
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].dstBinding =
pLayoutInfo->ObjectInfo.DescriptorSetLayout.pBindings[b].binding;
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].srcArrayElement =
0; // defaulting to 0, no way to know for sure at this time
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].srcSet =
0; // defaulting to 0, no way to know for sure at this time
setInfo.ObjectInfo.DescriptorSet.pCopyDescriptorSets[b].srcBinding =
0; // defaulting to 0, no way to know for sure at this time
}
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
// Manually written because it needs to use get_struct_chain_size and allocate some extra pointers (why?)
// Also since it needs to app the array of pointers and sub-buffers (see comments in function)
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites,
uint32_t descriptorCopyCount,
const VkCopyDescriptorSet* pDescriptorCopies) {
vktrace_trace_packet_header* pHeader;
packet_vkUpdateDescriptorSets* pPacket = NULL;
// begin custom code
size_t arrayByteCount = 0;
for (uint32_t i = 0; i < descriptorWriteCount; i++) {
arrayByteCount += get_struct_chain_size(&pDescriptorWrites[i]);
}
for (uint32_t i = 0; i < descriptorCopyCount; i++) {
arrayByteCount += get_struct_chain_size(&pDescriptorCopies[i]);
}
CREATE_TRACE_PACKET(vkUpdateDescriptorSets, arrayByteCount);
// end custom code
mdd(device)->devTable.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
pDescriptorCopies);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkUpdateDescriptorSets(pHeader);
pPacket->device = device;
pPacket->descriptorWriteCount = descriptorWriteCount;
// begin custom code
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorWrites),
descriptorWriteCount * sizeof(VkWriteDescriptorSet), pDescriptorWrites);
for (uint32_t i = 0; i < descriptorWriteCount; i++) {
switch (pPacket->pDescriptorWrites[i].descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorWrites[i].pImageInfo),
pDescriptorWrites[i].descriptorCount * sizeof(VkDescriptorImageInfo),
pDescriptorWrites[i].pImageInfo);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorWrites[i].pImageInfo));
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorWrites[i].pTexelBufferView),
pDescriptorWrites[i].descriptorCount * sizeof(VkBufferView),
pDescriptorWrites[i].pTexelBufferView);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorWrites[i].pTexelBufferView));
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorWrites[i].pBufferInfo),
pDescriptorWrites[i].descriptorCount * sizeof(VkDescriptorBufferInfo),
pDescriptorWrites[i].pBufferInfo);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorWrites[i].pBufferInfo));
} break;
default:
break;
}
}
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorWrites));
pPacket->descriptorCopyCount = descriptorCopyCount;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorCopies),
descriptorCopyCount * sizeof(VkCopyDescriptorSet), pDescriptorCopies);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorCopies));
// end custom code
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
for (uint32_t i = 0; i < descriptorWriteCount; i++) {
trim::ObjectInfo* pInfo = trim::get_DescriptorSet_objectInfo(pDescriptorWrites[i].dstSet);
if (pInfo != NULL) {
// find existing writeDescriptorSet info to update.
VkWriteDescriptorSet* pWriteDescriptorSet = NULL;
for (uint32_t w = 0; w < pInfo->ObjectInfo.DescriptorSet.numBindings; w++) {
if (pInfo->ObjectInfo.DescriptorSet.pWriteDescriptorSets[w].dstBinding == pDescriptorWrites[i].dstBinding &&
pInfo->ObjectInfo.DescriptorSet.pWriteDescriptorSets[w].descriptorType ==
pDescriptorWrites[i].descriptorType) {
pWriteDescriptorSet = &pInfo->ObjectInfo.DescriptorSet.pWriteDescriptorSets[w];
pInfo->ObjectInfo.DescriptorSet.writeDescriptorCount++;
pWriteDescriptorSet->dstArrayElement = pDescriptorWrites[i].dstArrayElement;
if (pDescriptorWrites[i].pImageInfo != nullptr) {
memcpy(const_cast<VkDescriptorImageInfo*>(pWriteDescriptorSet->pImageInfo),
pDescriptorWrites[i].pImageInfo,
sizeof(VkDescriptorImageInfo) * pWriteDescriptorSet->descriptorCount);
pWriteDescriptorSet->pBufferInfo = nullptr;
pWriteDescriptorSet->pTexelBufferView = nullptr;
}
if (pDescriptorWrites[i].pBufferInfo != nullptr) {
memcpy(const_cast<VkDescriptorBufferInfo*>(pWriteDescriptorSet->pBufferInfo),
pDescriptorWrites[i].pBufferInfo,
sizeof(VkDescriptorBufferInfo) * pWriteDescriptorSet->descriptorCount);
pWriteDescriptorSet->pImageInfo = nullptr;
pWriteDescriptorSet->pTexelBufferView = nullptr;
}
if (pDescriptorWrites[i].pTexelBufferView != nullptr) {
memcpy(const_cast<VkBufferView*>(pWriteDescriptorSet->pTexelBufferView),
pDescriptorWrites[i].pTexelBufferView,
sizeof(VkBufferView) * pWriteDescriptorSet->descriptorCount);
pWriteDescriptorSet->pImageInfo = nullptr;
pWriteDescriptorSet->pBufferInfo = nullptr;
}
break;
}
}
}
}
for (uint32_t i = 0; i < descriptorCopyCount; i++) {
trim::ObjectInfo* pInfo = trim::get_DescriptorSet_objectInfo(pDescriptorCopies[i].dstSet);
if (pInfo != NULL) {
// find existing CopyDescriptorSet info to update, or allocate space for a new one.
VkCopyDescriptorSet* pCopyDescriptorSet = NULL;
for (uint32_t c = 0; c < pInfo->ObjectInfo.DescriptorSet.numBindings; c++) {
if (pInfo->ObjectInfo.DescriptorSet.pCopyDescriptorSets[c].dstSet == pDescriptorCopies[i].dstSet &&
pInfo->ObjectInfo.DescriptorSet.pCopyDescriptorSets[c].dstBinding == pDescriptorCopies[i].dstBinding) {
pCopyDescriptorSet = &pInfo->ObjectInfo.DescriptorSet.pCopyDescriptorSets[c];
pInfo->ObjectInfo.DescriptorSet.copyDescriptorCount++;
pCopyDescriptorSet->dstArrayElement = pDescriptorCopies[i].dstArrayElement;
pCopyDescriptorSet->srcArrayElement = pDescriptorCopies[i].srcArrayElement;
pCopyDescriptorSet->srcBinding = pDescriptorCopies[i].srcBinding;
pCopyDescriptorSet->srcSet = pDescriptorCopies[i].srcSet;
break;
}
}
assert(pCopyDescriptorSet != NULL);
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkQueueSubmit(VkQueue queue, uint32_t submitCount,
const VkSubmitInfo* pSubmits, VkFence fence) {
#ifdef USE_PAGEGUARD_SPEEDUP
pageguardEnter();
#if defined(PLATFORM_LINUX)
getMappedDirtyPagesLinux();
#endif
flushAllChangedMappedMemory(&vkFlushMappedMemoryRangesWithoutAPICall);
resetAllReadFlagAndPageGuard();
pageguardExit();
#endif
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkQueueSubmit* pPacket = NULL;
size_t arrayByteCount = 0;
for (uint32_t i = 0; i < submitCount; ++i) {
arrayByteCount += vk_size_vksubmitinfo(&pSubmits[i]);
}
CREATE_TRACE_PACKET(vkQueueSubmit, arrayByteCount);
result = mdd(queue)->devTable.QueueSubmit(queue, submitCount, pSubmits, fence);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkQueueSubmit(pHeader);
pPacket->queue = queue;
pPacket->submitCount = submitCount;
pPacket->fence = fence;
pPacket->result = result;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSubmits), submitCount * sizeof(VkSubmitInfo), pSubmits);
for (uint32_t i = 0; i < submitCount; ++i) {
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSubmits[i].pCommandBuffers),
pPacket->pSubmits[i].commandBufferCount * sizeof(VkCommandBuffer),
pSubmits[i].pCommandBuffers);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSubmits[i].pCommandBuffers));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSubmits[i].pWaitSemaphores),
pPacket->pSubmits[i].waitSemaphoreCount * sizeof(VkSemaphore),
pSubmits[i].pWaitSemaphores);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSubmits[i].pWaitSemaphores));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSubmits[i].pSignalSemaphores),
pPacket->pSubmits[i].signalSemaphoreCount * sizeof(VkSemaphore),
pSubmits[i].pSignalSemaphores);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSubmits[i].pSignalSemaphores));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSubmits[i].pWaitDstStageMask),
pPacket->pSubmits[i].waitSemaphoreCount * sizeof(VkPipelineStageFlags),
pSubmits[i].pWaitDstStageMask);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSubmits[i].pWaitDstStageMask));
}
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSubmits));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
// when we're not trimming, we just need to track the queue
vktrace_finalize_trace_packet(pHeader);
if (result == VK_SUCCESS) {
trim::ObjectInfo* pFenceInfo = trim::get_Fence_objectInfo(fence);
if (pFenceInfo != NULL) {
pFenceInfo->ObjectInfo.Fence.signaled = true;
}
if (pSubmits != NULL) {
for (uint32_t i = 0; i < submitCount; i++) {
// Update attachment objects based on RenderPass transitions
for (uint32_t c = 0; c < pSubmits[i].commandBufferCount; c++) {
trim::ObjectInfo* pCBInfo = trim::get_CommandBuffer_objectInfo(pSubmits[i].pCommandBuffers[c]);
pCBInfo->ObjectInfo.CommandBuffer.submitQueue = queue;
// apply image transitions
std::list<trim::ImageTransition> imageTransitions =
trim::GetImageTransitions(pSubmits[i].pCommandBuffers[c]);
for (std::list<trim::ImageTransition>::iterator transition = imageTransitions.begin();
transition != imageTransitions.end(); transition++) {
trim::ObjectInfo* pImage = trim::get_Image_objectInfo(transition->image);
if (pImage != nullptr) {
pImage->ObjectInfo.Image.mostRecentLayout = transition->finalLayout;
pImage->ObjectInfo.Image.accessFlags = transition->dstAccessMask;
}
}
// apply buffer transitions
std::list<trim::BufferTransition> bufferTransitions =
trim::GetBufferTransitions(pSubmits[i].pCommandBuffers[c]);
for (std::list<trim::BufferTransition>::iterator transition = bufferTransitions.begin();
transition != bufferTransitions.end(); transition++) {
trim::ObjectInfo* pBuffer = trim::get_Buffer_objectInfo(transition->buffer);
if (pBuffer != nullptr) {
pBuffer->ObjectInfo.Buffer.accessFlags = transition->dstAccessMask;
}
}
}
if (pSubmits[i].pWaitSemaphores != NULL) {
for (uint32_t w = 0; w < pSubmits[i].waitSemaphoreCount; w++) {
trim::ObjectInfo* pInfo = trim::get_Semaphore_objectInfo(pSubmits[i].pWaitSemaphores[w]);
if (pInfo != NULL) {
pInfo->ObjectInfo.Semaphore.signaledOnQueue = VK_NULL_HANDLE;
}
}
}
if (pSubmits[i].pSignalSemaphores != NULL) {
for (uint32_t s = 0; s < pSubmits[i].signalSemaphoreCount; s++) {
trim::ObjectInfo* pInfo = trim::get_Semaphore_objectInfo(pSubmits[i].pSignalSemaphores[s]);
if (pInfo != NULL) {
pInfo->ObjectInfo.Semaphore.signaledOnQueue = queue;
}
}
}
}
}
}
if (g_trimIsInTrim) {
if (pSubmits != NULL && pSubmits->pCommandBuffers != NULL) {
for (uint32_t s = 0; s < submitCount; s++) {
for (uint32_t i = 0; i < pSubmits[s].commandBufferCount; i++) {
trim::mark_CommandBuffer_reference(pSubmits[s].pCommandBuffers[i]);
}
}
}
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount,
const VkBindSparseInfo* pBindInfo, VkFence fence) {
vktrace_trace_packet_header* pHeader;
VkResult result;
packet_vkQueueBindSparse* pPacket = NULL;
size_t arrayByteCount = 0;
uint32_t i = 0;
for (i = 0; i < bindInfoCount; ++i) {
arrayByteCount += vk_size_vkbindsparseinfo(&pBindInfo[i]);
}
CREATE_TRACE_PACKET(vkQueueBindSparse, arrayByteCount + 2 * sizeof(VkDeviceMemory));
result = mdd(queue)->devTable.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkQueueBindSparse(pHeader);
pPacket->queue = queue;
pPacket->bindInfoCount = bindInfoCount;
pPacket->fence = fence;
pPacket->result = result;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBindInfo), bindInfoCount * sizeof(VkBindSparseInfo), pBindInfo);
for (i = 0; i < bindInfoCount; ++i) {
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBindInfo[i].pBufferBinds),
pPacket->pBindInfo[i].bufferBindCount * sizeof(VkSparseBufferMemoryBindInfo),
pBindInfo[i].pBufferBinds);
for (uint32_t j = 0; j < pPacket->pBindInfo[i].bufferBindCount; j++) {
VkSparseBufferMemoryBindInfo* pSparseBufferMemoryBindInfo =
(VkSparseBufferMemoryBindInfo*)&pPacket->pBindInfo[i].pBufferBinds[j];
const VkSparseBufferMemoryBindInfo* pSparseBufMemBndInf = &pBindInfo[i].pBufferBinds[j];
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pSparseBufferMemoryBindInfo->pBinds),
pSparseBufferMemoryBindInfo->bindCount * sizeof(VkSparseMemoryBind),
pSparseBufMemBndInf->pBinds);
vktrace_finalize_buffer_address(pHeader, (void**)&(pSparseBufferMemoryBindInfo->pBinds));
}
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBindInfo[i].pBufferBinds));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBindInfo[i].pImageBinds),
pPacket->pBindInfo[i].imageBindCount * sizeof(VkSparseImageMemoryBindInfo),
pBindInfo[i].pImageOpaqueBinds);
for (uint32_t j = 0; j < pPacket->pBindInfo[i].imageBindCount; j++) {
VkSparseImageMemoryBindInfo* pSparseImageMemoryBindInfo =
(VkSparseImageMemoryBindInfo*)&pPacket->pBindInfo[i].pImageBinds[j];
const VkSparseImageMemoryBindInfo* pSparseImgMemBndInf = &pBindInfo[i].pImageBinds[j];
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pSparseImageMemoryBindInfo->pBinds),
pSparseImageMemoryBindInfo->bindCount * sizeof(VkSparseImageMemoryBind),
pSparseImgMemBndInf->pBinds);
vktrace_finalize_buffer_address(pHeader, (void**)&(pSparseImageMemoryBindInfo->pBinds));
}
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBindInfo[i].pImageBinds));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBindInfo[i].pImageOpaqueBinds),
pPacket->pBindInfo[i].imageOpaqueBindCount * sizeof(VkSparseImageOpaqueMemoryBindInfo),
pBindInfo[i].pImageOpaqueBinds);
for (uint32_t j = 0; j < pPacket->pBindInfo[i].imageOpaqueBindCount; j++) {
VkSparseImageOpaqueMemoryBindInfo* pSparseImageOpaqueMemoryBindInfo =
(VkSparseImageOpaqueMemoryBindInfo*)&pPacket->pBindInfo[i].pImageOpaqueBinds[j];
const VkSparseImageOpaqueMemoryBindInfo* pSparseImgOpqMemBndInf = &pBindInfo[i].pImageOpaqueBinds[j];
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pSparseImageOpaqueMemoryBindInfo->pBinds),
pSparseImageOpaqueMemoryBindInfo->bindCount * sizeof(VkSparseMemoryBind),
pSparseImgOpqMemBndInf->pBinds);
vktrace_finalize_buffer_address(pHeader, (void**)&(pSparseImageOpaqueMemoryBindInfo->pBinds));
}
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBindInfo[i].pImageOpaqueBinds));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBindInfo[i].pWaitSemaphores),
pPacket->pBindInfo[i].waitSemaphoreCount * sizeof(VkSemaphore),
pBindInfo[i].pWaitSemaphores);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBindInfo[i].pWaitSemaphores));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBindInfo[i].pSignalSemaphores),
pPacket->pBindInfo[i].signalSemaphoreCount * sizeof(VkSemaphore),
pBindInfo[i].pSignalSemaphores);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBindInfo[i].pSignalSemaphores));
}
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBindInfo));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkCmdWaitEvents(
VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers) {
vktrace_trace_packet_header* pHeader;
packet_vkCmdWaitEvents* pPacket = NULL;
size_t customSize;
customSize = (eventCount * sizeof(VkEvent)) + (memoryBarrierCount * sizeof(VkMemoryBarrier)) +
(bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier)) +
(imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier));
CREATE_TRACE_PACKET(vkCmdWaitEvents, customSize);
mdd(commandBuffer)
->devTable.CmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount,
pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount,
pImageMemoryBarriers);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCmdWaitEvents(pHeader);
pPacket->commandBuffer = commandBuffer;
pPacket->eventCount = eventCount;
pPacket->srcStageMask = srcStageMask;
pPacket->dstStageMask = dstStageMask;
pPacket->memoryBarrierCount = memoryBarrierCount;
pPacket->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
pPacket->imageMemoryBarrierCount = imageMemoryBarrierCount;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pEvents), eventCount * sizeof(VkEvent), pEvents);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pEvents));
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pMemoryBarriers), memoryBarrierCount * sizeof(VkMemoryBarrier),
pMemoryBarriers);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBufferMemoryBarriers),
bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier), pBufferMemoryBarriers);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pImageMemoryBarriers),
imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier), pImageMemoryBarriers);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pMemoryBarriers));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBufferMemoryBarriers));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pImageMemoryBarriers));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
for (uint32_t i = 0; i < imageMemoryBarrierCount; i++) {
trim::ObjectInfo* pImageInfo = trim::get_Image_objectInfo(pImageMemoryBarriers[i].image);
assert(pImageInfo != nullptr);
if (pImageInfo != nullptr) {
pImageInfo->ObjectInfo.Image.mostRecentLayout = pImageMemoryBarriers[i].newLayout;
}
}
trim::add_CommandBuffer_call(commandBuffer, trim::copy_packet(pHeader));
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
}
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkCmdPipelineBarrier(
VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers) {
vktrace_trace_packet_header* pHeader;
packet_vkCmdPipelineBarrier* pPacket = NULL;
size_t customSize;
customSize = (memoryBarrierCount * sizeof(VkMemoryBarrier)) + (bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier)) +
(imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier));
CREATE_TRACE_PACKET(vkCmdPipelineBarrier, customSize);
mdd(commandBuffer)
->devTable.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount,
pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount,
pImageMemoryBarriers);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCmdPipelineBarrier(pHeader);
pPacket->commandBuffer = commandBuffer;
pPacket->srcStageMask = srcStageMask;
pPacket->dstStageMask = dstStageMask;
pPacket->dependencyFlags = dependencyFlags;
pPacket->memoryBarrierCount = memoryBarrierCount;
pPacket->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
pPacket->imageMemoryBarrierCount = imageMemoryBarrierCount;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pMemoryBarriers), memoryBarrierCount * sizeof(VkMemoryBarrier),
pMemoryBarriers);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBufferMemoryBarriers),
bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier), pBufferMemoryBarriers);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pImageMemoryBarriers),
imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier), pImageMemoryBarriers);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pMemoryBarriers));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBufferMemoryBarriers));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pImageMemoryBarriers));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
for (uint32_t i = 0; i < imageMemoryBarrierCount; i++) {
trim::ObjectInfo* pImageInfo = trim::get_Image_objectInfo(pImageMemoryBarriers[i].image);
assert(pImageInfo != nullptr);
if (pImageInfo != nullptr) {
trim::ImageTransition transition;
transition.image = pImageMemoryBarriers[i].image;
transition.initialLayout = pImageMemoryBarriers[i].oldLayout;
transition.finalLayout = pImageMemoryBarriers[i].newLayout;
transition.srcAccessMask = pImageMemoryBarriers[i].srcAccessMask;
transition.dstAccessMask = pImageMemoryBarriers[i].dstAccessMask;
trim::AddImageTransition(commandBuffer, transition);
}
}
for (uint32_t i = 0; i < bufferMemoryBarrierCount; i++) {
trim::ObjectInfo* pBufferInfo = trim::get_Buffer_objectInfo(pBufferMemoryBarriers[i].buffer);
assert(pBufferInfo != nullptr);
if (pBufferInfo != nullptr) {
trim::BufferTransition transition;
transition.buffer = pBufferMemoryBarriers[i].buffer;
transition.srcAccessMask = pBufferMemoryBarriers[i].srcAccessMask;
transition.dstAccessMask = pBufferMemoryBarriers[i].dstAccessMask;
trim::AddBufferTransition(commandBuffer, transition);
}
}
trim::add_CommandBuffer_call(commandBuffer, trim::copy_packet(pHeader));
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
}
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
VkShaderStageFlags stageFlags, uint32_t offset,
uint32_t size, const void* pValues) {
vktrace_trace_packet_header* pHeader;
packet_vkCmdPushConstants* pPacket = NULL;
CREATE_TRACE_PACKET(vkCmdPushConstants, size);
mdd(commandBuffer)->devTable.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCmdPushConstants(pHeader);
pPacket->commandBuffer = commandBuffer;
pPacket->layout = layout;
pPacket->stageFlags = stageFlags;
pPacket->offset = offset;
pPacket->size = size;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pValues), size, pValues);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pValues));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::add_CommandBuffer_call(commandBuffer, trim::copy_packet(pHeader));
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache,
size_t* pDataSize, void* pData) {
vktrace_trace_packet_header* pHeader;
VkResult result;
packet_vkGetPipelineCacheData* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
startTime = vktrace_get_time();
result = mdd(device)->devTable.GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
endTime = vktrace_get_time();
assert(pDataSize);
CREATE_TRACE_PACKET(vkGetPipelineCacheData, sizeof(size_t) + ROUNDUP_TO_4(*pDataSize));
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkGetPipelineCacheData(pHeader);
pPacket->device = device;
pPacket->pipelineCache = pipelineCache;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDataSize), sizeof(size_t), pDataSize);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pData), ROUNDUP_TO_4(*pDataSize), pData);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDataSize));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pData));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
// The accurate size of VkGraphicsPipelineCreateInfo can be got from
// get_struct_chain_size, but it's needed to ROUNDUP_TO_4 because
// VkGraphicsPipelineCreateInfo might include valid entry point name of shader.
size_t get_VkGraphicsPipelineCreateInfo_size_ROUNDUP_TO_4(const VkGraphicsPipelineCreateInfo* pCreateInfos) {
size_t entryPointNameLength = 0;
size_t struct_size = get_struct_chain_size(pCreateInfos);
if ((pCreateInfos->stageCount) && (pCreateInfos->pStages != nullptr)) {
VkPipelineShaderStageCreateInfo* pStage = const_cast<VkPipelineShaderStageCreateInfo*>(pCreateInfos->pStages);
for (uint32_t i = 0; i < pCreateInfos->stageCount; i++) {
if (pStage->pName) {
entryPointNameLength = strlen(pStage->pName) + 1;
struct_size += ROUNDUP_TO_4(entryPointNameLength) - entryPointNameLength;
}
++pStage;
}
}
return struct_size;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkGraphicsPipelineCreateInfo* pCreateInfos,
const VkAllocationCallbacks* pAllocator,
VkPipeline* pPipelines) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateGraphicsPipelines* pPacket = NULL;
size_t total_size = 0;
for (uint32_t i = 0; i < createInfoCount; i++) {
total_size += get_VkGraphicsPipelineCreateInfo_size_ROUNDUP_TO_4(&pCreateInfos[i]);
}
CREATE_TRACE_PACKET(vkCreateGraphicsPipelines,
total_size + sizeof(VkAllocationCallbacks) + createInfoCount * sizeof(VkPipeline));
result =
mdd(device)->devTable.CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCreateGraphicsPipelines(pHeader);
pPacket->device = device;
pPacket->pipelineCache = pipelineCache;
pPacket->createInfoCount = createInfoCount;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfos),
createInfoCount * sizeof(VkGraphicsPipelineCreateInfo), pCreateInfos);
add_VkGraphicsPipelineCreateInfos_to_trace_packet(pHeader, (VkGraphicsPipelineCreateInfo*)pPacket->pCreateInfos, pCreateInfos,
createInfoCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPipelines), createInfoCount * sizeof(VkPipeline), pPipelines);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfos));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPipelines));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
for (uint32_t i = 0; i < createInfoCount; i++) {
trim::ObjectInfo& info = trim::add_Pipeline_object(pPipelines[i]);
info.belongsToDevice = device;
info.ObjectInfo.Pipeline.isGraphicsPipeline = true;
info.ObjectInfo.Pipeline.pipelineCache = pipelineCache;
info.ObjectInfo.Pipeline.renderPassVersion = trim::get_RenderPassVersion(pCreateInfos[i].renderPass);
info.ObjectInfo.Pipeline.shaderModuleCreateInfoCount = pCreateInfos[i].stageCount;
info.ObjectInfo.Pipeline.pShaderModuleCreateInfos =
VKTRACE_NEW_ARRAY(VkShaderModuleCreateInfo, pCreateInfos[i].stageCount);
for (uint32_t stageIndex = 0; stageIndex < info.ObjectInfo.Pipeline.shaderModuleCreateInfoCount; stageIndex++) {
trim::ObjectInfo* pShaderModuleInfo = trim::get_ShaderModule_objectInfo(pCreateInfos[i].pStages[stageIndex].module);
if (pShaderModuleInfo != nullptr) {
trim::StateTracker::copy_VkShaderModuleCreateInfo(
&info.ObjectInfo.Pipeline.pShaderModuleCreateInfos[stageIndex],
pShaderModuleInfo->ObjectInfo.ShaderModule.createInfo);
}
}
trim::StateTracker::copy_VkGraphicsPipelineCreateInfo(&info.ObjectInfo.Pipeline.graphicsPipelineCreateInfo,
pCreateInfos[i]);
if (pAllocator != NULL) {
info.ObjectInfo.Pipeline.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
uint64_t getVkComputePipelineCreateInfosAdditionalSize(uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos) {
uint64_t uiRet = 0;
VkPipelineShaderStageCreateInfo* packetShader;
for (uint32_t i = 0; i < createInfoCount; i++) {
uiRet += sizeof(VkPipelineShaderStageCreateInfo);
packetShader = (VkPipelineShaderStageCreateInfo*)&pCreateInfos[i].stage;
uiRet += strlen(packetShader->pName) + 1;
uiRet += sizeof(VkSpecializationInfo);
if (packetShader->pSpecializationInfo != NULL) {
uiRet += sizeof(VkSpecializationMapEntry) * packetShader->pSpecializationInfo->mapEntryCount;
uiRet += packetShader->pSpecializationInfo->dataSize;
}
}
return uiRet;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache,
uint32_t createInfoCount,
const VkComputePipelineCreateInfo* pCreateInfos,
const VkAllocationCallbacks* pAllocator,
VkPipeline* pPipelines) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateComputePipelines* pPacket = NULL;
CREATE_TRACE_PACKET(vkCreateComputePipelines, createInfoCount * sizeof(VkComputePipelineCreateInfo) +
getVkComputePipelineCreateInfosAdditionalSize(createInfoCount, pCreateInfos) +
sizeof(VkAllocationCallbacks) + createInfoCount * sizeof(VkPipeline));
result =
mdd(device)->devTable.CreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCreateComputePipelines(pHeader);
pPacket->device = device;
pPacket->pipelineCache = pipelineCache;
pPacket->createInfoCount = createInfoCount;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfos),
createInfoCount * sizeof(VkComputePipelineCreateInfo), pCreateInfos);
add_VkComputePipelineCreateInfos_to_trace_packet(pHeader, (VkComputePipelineCreateInfo*)pPacket->pCreateInfos, pCreateInfos,
createInfoCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPipelines), createInfoCount * sizeof(VkPipeline), pPipelines);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfos));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPipelines));
if (!g_trimEnabled) {
// trim not enabled, send packet as usual
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
for (uint32_t i = 0; i < createInfoCount; i++) {
trim::ObjectInfo& info = trim::add_Pipeline_object(pPipelines[i]);
info.belongsToDevice = device;
info.ObjectInfo.Pipeline.isGraphicsPipeline = false;
info.ObjectInfo.Pipeline.pipelineCache = pipelineCache;
info.ObjectInfo.Pipeline.shaderModuleCreateInfoCount = 1;
info.ObjectInfo.Pipeline.pShaderModuleCreateInfos = VKTRACE_NEW(VkShaderModuleCreateInfo);
trim::ObjectInfo* pShaderModuleInfo = trim::get_ShaderModule_objectInfo(pCreateInfos[i].stage.module);
if (pShaderModuleInfo != nullptr) {
trim::StateTracker::copy_VkShaderModuleCreateInfo(&info.ObjectInfo.Pipeline.pShaderModuleCreateInfos[0],
pShaderModuleInfo->ObjectInfo.ShaderModule.createInfo);
}
trim::StateTracker::copy_VkComputePipelineCreateInfo(&info.ObjectInfo.Pipeline.computePipelineCreateInfo,
pCreateInfos[i]);
if (pAllocator != NULL) {
info.ObjectInfo.Pipeline.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreatePipelineCache(VkDevice device,
const VkPipelineCacheCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkPipelineCache* pPipelineCache) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreatePipelineCache* pPacket = NULL;
// Need to round up the size when we create the packet because pCreateInfo->initialDataSize may not be a mult of 4
CREATE_TRACE_PACKET(vkCreatePipelineCache, ROUNDUP_TO_4(get_struct_chain_size((void*)pCreateInfo) +
sizeof(VkAllocationCallbacks) + sizeof(VkPipelineCache)));
result = mdd(device)->devTable.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCreatePipelineCache(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkPipelineCacheCreateInfo), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pInitialData),
ROUNDUP_TO_4(pPacket->pCreateInfo->initialDataSize), pCreateInfo->pInitialData);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPipelineCache), sizeof(VkPipelineCache), pPipelineCache);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pInitialData));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPipelineCache));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_PipelineCache_object(*pPipelineCache);
info.belongsToDevice = device;
info.ObjectInfo.PipelineCache.pCreatePacket = trim::copy_packet(pHeader);
if (pAllocator != NULL) {
info.ObjectInfo.PipelineCache.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR void VKAPI_CALL __HOOKED_vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents) {
vktrace_trace_packet_header* pHeader;
packet_vkCmdBeginRenderPass* pPacket = NULL;
size_t clearValueSize = sizeof(VkClearValue) * pRenderPassBegin->clearValueCount;
CREATE_TRACE_PACKET(vkCmdBeginRenderPass, sizeof(VkRenderPassBeginInfo) + clearValueSize);
mdd(commandBuffer)->devTable.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCmdBeginRenderPass(pHeader);
pPacket->commandBuffer = commandBuffer;
pPacket->contents = contents;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pRenderPassBegin), sizeof(VkRenderPassBeginInfo),
pRenderPassBegin);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pRenderPassBegin->pClearValues), clearValueSize,
pRenderPassBegin->pClearValues);
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pRenderPassBegin->pClearValues));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pRenderPassBegin));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::add_CommandBuffer_call(commandBuffer, trim::copy_packet(pHeader));
trim::ObjectInfo* pCommandBuffer = trim::get_CommandBuffer_objectInfo(commandBuffer);
if (pCommandBuffer != nullptr) {
pCommandBuffer->ObjectInfo.CommandBuffer.activeRenderPass = pRenderPassBegin->renderPass;
trim::ObjectInfo* pFramebuffer = trim::get_Framebuffer_objectInfo(pRenderPassBegin->framebuffer);
trim::ObjectInfo* pRenderPass = trim::get_RenderPass_objectInfo(pRenderPassBegin->renderPass);
assert(pRenderPass != nullptr && pFramebuffer != nullptr);
if (pRenderPass != nullptr && pFramebuffer != nullptr) {
assert(pRenderPass->ObjectInfo.RenderPass.attachmentCount == pFramebuffer->ObjectInfo.Framebuffer.attachmentCount);
uint32_t minAttachmentCount = std::min<uint32_t>(pRenderPass->ObjectInfo.RenderPass.attachmentCount,
pFramebuffer->ObjectInfo.Framebuffer.attachmentCount);
for (uint32_t i = 0; i < minAttachmentCount; i++) {
trim::ObjectInfo* pImageView =
trim::get_ImageView_objectInfo(pFramebuffer->ObjectInfo.Framebuffer.pAttachments[i]);
assert(pImageView != nullptr);
if (pImageView != nullptr) {
pRenderPass->ObjectInfo.RenderPass.pAttachments[i].image = pImageView->ObjectInfo.ImageView.image;
} else {
pRenderPass->ObjectInfo.RenderPass.pAttachments[i].image = VK_NULL_HANDLE;
}
}
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
uint32_t descriptorSetCount,
const VkDescriptorSet* pDescriptorSets) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkFreeDescriptorSets* pPacket = NULL;
CREATE_TRACE_PACKET(vkFreeDescriptorSets, descriptorSetCount * sizeof(VkDescriptorSet));
result = mdd(device)->devTable.FreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkFreeDescriptorSets(pHeader);
pPacket->device = device;
pPacket->descriptorPool = descriptorPool;
pPacket->descriptorSetCount = descriptorSetCount;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorSets), descriptorSetCount * sizeof(VkDescriptorSet),
pDescriptorSets);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorSets));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo* pPoolInfo = trim::get_DescriptorPool_objectInfo(descriptorPool);
if (pPoolInfo != NULL &&
(pPoolInfo->ObjectInfo.DescriptorPool.createFlags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT) != 0) {
pPoolInfo->ObjectInfo.DescriptorPool.numSets -= descriptorSetCount;
for (uint32_t i = 0; i < descriptorSetCount; i++) {
// Clean up memory
trim::remove_DescriptorSet_object(pDescriptorSets[i]);
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkImage* pImage) {
vktrace_trace_packet_header* pHeader;
VkResult result;
packet_vkCreateImage* pPacket = NULL;
CREATE_TRACE_PACKET(vkCreateImage, get_struct_chain_size((void*)pCreateInfo) + sizeof(VkAllocationCallbacks) + sizeof(VkImage));
result = mdd(device)->devTable.CreateImage(device, pCreateInfo, pAllocator, pImage);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkCreateImage(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkImageCreateInfo), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pQueueFamilyIndices),
sizeof(uint32_t) * pCreateInfo->queueFamilyIndexCount, pCreateInfo->pQueueFamilyIndices);
add_extension_to_createimage_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pNext), pCreateInfo->pNext);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pImage), sizeof(VkImage), pImage);
pPacket->result = result;
if (g_trimEnabled) {
VkImageCreateInfo* pCreateInfo = const_cast<VkImageCreateInfo*>(pPacket->pCreateInfo);
pCreateInfo->usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pQueueFamilyIndices));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pImage));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
#if TRIM_USE_ORDERED_IMAGE_CREATION
trim::add_Image_call(trim::copy_packet(pHeader));
#endif // TRIM_USE_ORDERED_IMAGE_CREATION"
trim::ObjectInfo& info = trim::add_Image_object(*pImage);
info.belongsToDevice = device;
#if !TRIM_USE_ORDERED_IMAGE_CREATION
info.ObjectInfo.Image.pCreatePacket = trim::copy_packet(pHeader);
#endif //! TRIM_USE_ORDERED_IMAGE_CREATION
info.ObjectInfo.Image.bIsSwapchainImage = false;
info.ObjectInfo.Image.format = pCreateInfo->format;
info.ObjectInfo.Image.aspectMask = trim::getImageAspectFromFormat(pCreateInfo->format);
info.ObjectInfo.Image.extent = pCreateInfo->extent;
info.ObjectInfo.Image.mipLevels = pCreateInfo->mipLevels;
info.ObjectInfo.Image.arrayLayers = pCreateInfo->arrayLayers;
info.ObjectInfo.Image.sharingMode = pCreateInfo->sharingMode;
info.ObjectInfo.Image.queueFamilyIndex =
(pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT && pCreateInfo->pQueueFamilyIndices != NULL)
? pCreateInfo->pQueueFamilyIndices[0]
: 0;
info.ObjectInfo.Image.initialLayout = pCreateInfo->initialLayout;
info.ObjectInfo.Image.mostRecentLayout = pCreateInfo->initialLayout;
if (pAllocator != NULL) {
info.ObjectInfo.Image.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer)
{
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateBuffer* pPacket = NULL;
CREATE_TRACE_PACKET(vkCreateBuffer, get_struct_chain_size((void*)pCreateInfo) + sizeof(VkAllocationCallbacks) + sizeof(VkBuffer));
VkBufferCreateInfo replayCreateInfo = *pCreateInfo;
VkBufferCreateInfo trimCreateInfo = *pCreateInfo;
if (g_trimEnabled) {
// need to add TRANSFER_SRC usage to the buffer so that we can copy out of it.
trimCreateInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
pCreateInfo = &trimCreateInfo;
}
result = mdd(device)->devTable.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
vktrace_set_packet_entrypoint_end_time(pHeader);
if (g_trimEnabled) {
// need to add TRANSFER_DST usage to the buffer so that we can recreate it.
replayCreateInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
pCreateInfo = &replayCreateInfo;
}
pPacket = interpret_body_as_vkCreateBuffer(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkBufferCreateInfo), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pQueueFamilyIndices), sizeof(uint32_t) * pCreateInfo->queueFamilyIndexCount, pCreateInfo->pQueueFamilyIndices);
add_extension_to_createbuffer_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pNext), pCreateInfo->pNext);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBuffer), sizeof(VkBuffer), pBuffer);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pQueueFamilyIndices));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pBuffer));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo &info = trim::add_Buffer_object(*pBuffer);
info.belongsToDevice = device;
info.ObjectInfo.Buffer.pCreatePacket = trim::copy_packet(pHeader);
info.ObjectInfo.Buffer.size = pCreateInfo->size;
if (pCreateInfo->queueFamilyIndexCount > 0) { info.ObjectInfo.Buffer.queueFamilyIndex = pCreateInfo->pQueueFamilyIndices[0]; }
if (pAllocator != NULL) {
info.ObjectInfo.Buffer.pAllocator = pAllocator;
}
if (pAllocator != NULL) {
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
} }
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkGetPhysicalDeviceSurfaceCapabilitiesKHR* pPacket = NULL;
CREATE_TRACE_PACKET(vkGetPhysicalDeviceSurfaceCapabilitiesKHR, sizeof(VkSurfaceCapabilitiesKHR));
result = mid(physicalDevice)->instTable.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
pPacket = interpret_body_as_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(pHeader);
pPacket->physicalDevice = physicalDevice;
pPacket->surface = surface;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSurfaceCapabilities), sizeof(VkSurfaceCapabilitiesKHR),
pSurfaceCapabilities);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSurfaceCapabilities));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
uint32_t* pSurfaceFormatCount,
VkSurfaceFormatKHR* pSurfaceFormats) {
VkResult result;
vktrace_trace_packet_header* pHeader;
size_t _dataSize;
packet_vkGetPhysicalDeviceSurfaceFormatsKHR* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
startTime = vktrace_get_time();
result = mid(physicalDevice)
->instTable.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
endTime = vktrace_get_time();
_dataSize = (pSurfaceFormatCount == NULL || pSurfaceFormats == NULL) ? 0 : (*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
CREATE_TRACE_PACKET(vkGetPhysicalDeviceSurfaceFormatsKHR, sizeof(uint32_t) + _dataSize);
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkGetPhysicalDeviceSurfaceFormatsKHR(pHeader);
pPacket->physicalDevice = physicalDevice;
pPacket->surface = surface;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSurfaceFormatCount), sizeof(uint32_t), pSurfaceFormatCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSurfaceFormats), _dataSize, pSurfaceFormats);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSurfaceFormatCount));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSurfaceFormats));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
uint32_t* pPresentModeCount,
VkPresentModeKHR* pPresentModes) {
VkResult result;
vktrace_trace_packet_header* pHeader;
size_t _dataSize;
packet_vkGetPhysicalDeviceSurfacePresentModesKHR* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
startTime = vktrace_get_time();
result = mid(physicalDevice)
->instTable.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes);
endTime = vktrace_get_time();
_dataSize = (pPresentModeCount == NULL || pPresentModes == NULL) ? 0 : (*pPresentModeCount * sizeof(VkPresentModeKHR));
CREATE_TRACE_PACKET(vkGetPhysicalDeviceSurfacePresentModesKHR, sizeof(uint32_t) + _dataSize);
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkGetPhysicalDeviceSurfacePresentModesKHR(pHeader);
pPacket->physicalDevice = physicalDevice;
pPacket->surface = surface;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPresentModeCount), sizeof(uint32_t), pPresentModeCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPresentModes), _dataSize, pPresentModes);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPresentModeCount));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPresentModes));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateSwapchainKHR(VkDevice device,
const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSwapchainKHR* pSwapchain) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateSwapchainKHR* pPacket = NULL;
CREATE_TRACE_PACKET(vkCreateSwapchainKHR,
vk_size_vkswapchaincreateinfokhr(pCreateInfo) + sizeof(VkSwapchainKHR) + sizeof(VkAllocationCallbacks));
result = mdd(device)->devTable.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
pPacket = interpret_body_as_vkCreateSwapchainKHR(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkSwapchainCreateInfoKHR), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSwapchain), sizeof(VkSwapchainKHR), pSwapchain);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo->pQueueFamilyIndices),
pCreateInfo->queueFamilyIndexCount * sizeof(uint32_t), pCreateInfo->pQueueFamilyIndices);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo->pQueueFamilyIndices));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSwapchain));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_SwapchainKHR_object(*pSwapchain);
info.belongsToDevice = device;
info.ObjectInfo.SwapchainKHR.pCreatePacket = trim::copy_packet(pHeader);
if (pAllocator != NULL) {
info.ObjectInfo.SwapchainKHR.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain,
uint32_t* pSwapchainImageCount,
VkImage* pSwapchainImages) {
VkResult result;
vktrace_trace_packet_header* pHeader;
size_t _dataSize;
packet_vkGetSwapchainImagesKHR* pPacket = NULL;
uint64_t startTime;
uint64_t endTime;
uint64_t vktraceStartTime = vktrace_get_time();
startTime = vktrace_get_time();
result = mdd(device)->devTable.GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
endTime = vktrace_get_time();
_dataSize = (pSwapchainImageCount == NULL || pSwapchainImages == NULL) ? 0 : (*pSwapchainImageCount * sizeof(VkImage));
CREATE_TRACE_PACKET(vkGetSwapchainImagesKHR, sizeof(uint32_t) + _dataSize);
pHeader->vktrace_begin_time = vktraceStartTime;
pHeader->entrypoint_begin_time = startTime;
pHeader->entrypoint_end_time = endTime;
pPacket = interpret_body_as_vkGetSwapchainImagesKHR(pHeader);
pPacket->device = device;
pPacket->swapchain = swapchain;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSwapchainImageCount), sizeof(uint32_t), pSwapchainImageCount);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSwapchainImages), _dataSize, pSwapchainImages);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSwapchainImageCount));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSwapchainImages));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo* pInfo = trim::get_SwapchainKHR_objectInfo(swapchain);
if (pInfo != NULL) {
if (pSwapchainImageCount != NULL && pSwapchainImages == NULL) {
if (g_trimIsPreTrim) {
// only want to replay this call if it was made PRE trim frames.
pInfo->ObjectInfo.SwapchainKHR.pGetSwapchainImageCountPacket = trim::copy_packet(pHeader);
}
} else if (pSwapchainImageCount != NULL && pSwapchainImages != NULL) {
if (g_trimIsPreTrim) {
// only want to replay this call if it was made PRE trim frames.
pInfo->ObjectInfo.SwapchainKHR.pGetSwapchainImagesPacket = trim::copy_packet(pHeader);
}
for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
trim::ObjectInfo& imageInfo = trim::add_Image_object(pSwapchainImages[i]);
imageInfo.ObjectInfo.Image.bIsSwapchainImage = true;
}
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkQueuePresentKHR* pPacket = NULL;
size_t swapchainSize = pPresentInfo->swapchainCount * sizeof(VkSwapchainKHR);
size_t indexSize = pPresentInfo->swapchainCount * sizeof(uint32_t);
size_t semaSize = pPresentInfo->waitSemaphoreCount * sizeof(VkSemaphore);
size_t resultsSize = pPresentInfo->swapchainCount * sizeof(VkResult);
size_t totalSize = sizeof(VkPresentInfoKHR) + swapchainSize + indexSize + semaSize;
if (pPresentInfo->pResults != NULL) {
totalSize += resultsSize;
}
CREATE_TRACE_PACKET(vkQueuePresentKHR, totalSize);
result = mdd(queue)->devTable.QueuePresentKHR(queue, pPresentInfo);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkQueuePresentKHR(pHeader);
pPacket->queue = queue;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPresentInfo), sizeof(VkPresentInfoKHR), pPresentInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPresentInfo->pSwapchains), swapchainSize,
pPresentInfo->pSwapchains);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPresentInfo->pImageIndices), indexSize,
pPresentInfo->pImageIndices);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPresentInfo->pWaitSemaphores), semaSize,
pPresentInfo->pWaitSemaphores);
if (pPresentInfo->pResults != NULL) {
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pPresentInfo->pResults), resultsSize,
pPresentInfo->pResults);
}
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPresentInfo->pImageIndices));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPresentInfo->pSwapchains));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPresentInfo->pWaitSemaphores));
if (pPresentInfo->pResults != NULL) {
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPresentInfo->pResults));
}
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pPresentInfo));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (result == VK_SUCCESS && pPresentInfo != NULL && pPresentInfo->pWaitSemaphores != NULL) {
for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; i++) {
trim::ObjectInfo* pInfo = trim::get_Semaphore_objectInfo(pPresentInfo->pWaitSemaphores[i]);
if (pInfo != NULL) {
pInfo->ObjectInfo.Semaphore.signaledOnQueue = VK_NULL_HANDLE;
}
}
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
if (g_trimEnabled) {
if (trim::is_trim_trigger_enabled(trim::enum_trim_trigger::hotKey)) {
if (trim::is_hotkey_trim_triggered() && (!g_trimAlreadyFinished)) {
if (g_trimIsInTrim) {
trim::stop();
} else {
trim::start();
}
}
} else if (trim::is_trim_trigger_enabled(trim::enum_trim_trigger::frameCounter)) {
g_trimFrameCounter++;
if (g_trimFrameCounter == g_trimStartFrame) {
vktrace_LogAlways("Trim starting now at frame: %d", g_trimStartFrame);
trim::start();
}
if (g_trimEndFrame < UINT64_MAX && g_trimFrameCounter == g_trimEndFrame + 1) {
vktrace_LogAlways("Trim stopping now at frame: %d", g_trimEndFrame);
trim::stop();
}
}
}
return result;
}
/* TODO these can probably be moved into code gen */
#ifdef VK_USE_PLATFORM_WIN32_KHR
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateWin32SurfaceKHR(VkInstance instance,
const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateWin32SurfaceKHR* pPacket = NULL;
// don't bother with copying the actual win32 hinstance, hwnd into the trace packet, vkreplay has to use it's own anyway
CREATE_TRACE_PACKET(vkCreateWin32SurfaceKHR,
sizeof(VkSurfaceKHR) + sizeof(VkAllocationCallbacks) + sizeof(VkWin32SurfaceCreateInfoKHR));
result = mid(instance)->instTable.CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
pPacket = interpret_body_as_vkCreateWin32SurfaceKHR(pHeader);
pPacket->instance = instance;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkWin32SurfaceCreateInfoKHR), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSurface), sizeof(VkSurfaceKHR), pSurface);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSurface));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_SurfaceKHR_object(*pSurface);
info.belongsToInstance = instance;
info.ObjectInfo.SurfaceKHR.pCreatePacket = trim::copy_packet(pHeader);
if (pAllocator != NULL) {
info.ObjectInfo.SurfaceKHR.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL
__HOOKED_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
VkBool32 result;
vktrace_trace_packet_header* pHeader;
packet_vkGetPhysicalDeviceWin32PresentationSupportKHR* pPacket = NULL;
CREATE_TRACE_PACKET(vkGetPhysicalDeviceWin32PresentationSupportKHR, 0);
result = mid(physicalDevice)->instTable.GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
pPacket = interpret_body_as_vkGetPhysicalDeviceWin32PresentationSupportKHR(pHeader);
pPacket->physicalDevice = physicalDevice;
pPacket->queueFamilyIndex = queueFamilyIndex;
pPacket->result = result;
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateXcbSurfaceKHR(VkInstance instance,
const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface) {
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkCreateXcbSurfaceKHR* pPacket = NULL;
trim::set_keyboard_connection(pCreateInfo->connection);
// don't bother with copying the actual xcb window and connection into the trace packet, vkreplay has to use it's own anyway
CREATE_TRACE_PACKET(vkCreateXcbSurfaceKHR,
sizeof(VkSurfaceKHR) + sizeof(VkAllocationCallbacks) + sizeof(VkXcbSurfaceCreateInfoKHR));
result = mid(instance)->instTable.CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
pPacket = interpret_body_as_vkCreateXcbSurfaceKHR(pHeader);
pPacket->instance = instance;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkXcbSurfaceCreateInfoKHR), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSurface), sizeof(VkSurfaceKHR), pSurface);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSurface));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_SurfaceKHR_object(*pSurface);
info.belongsToInstance = instance;
info.ObjectInfo.SurfaceKHR.pCreatePacket = trim::copy_packet(pHeader);
if (pAllocator != NULL) {
info.ObjectInfo.SurfaceKHR.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL __HOOKED_vkGetPhysicalDeviceXcbPresentationSupportKHR(
VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id) {
VkBool32 result;
vktrace_trace_packet_header* pHeader;
packet_vkGetPhysicalDeviceXcbPresentationSupportKHR* pPacket = NULL;
// don't bother with copying the actual xcb visual_id and connection into the trace packet, vkreplay has to use it's own anyway
CREATE_TRACE_PACKET(vkGetPhysicalDeviceXcbPresentationSupportKHR, 0);
result = mid(physicalDevice)
->instTable.GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex, connection, visual_id);
pPacket = interpret_body_as_vkGetPhysicalDeviceXcbPresentationSupportKHR(pHeader);
pPacket->physicalDevice = physicalDevice;
pPacket->connection = connection;
pPacket->queueFamilyIndex = queueFamilyIndex;
pPacket->visual_id = visual_id;
pPacket->result = result;
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateXlibSurfaceKHR(VkInstance instance,
const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface) {
vktrace_trace_packet_header* pHeader;
VkResult result;
packet_vkCreateXlibSurfaceKHR* pPacket = NULL;
// don't bother with copying the actual xlib window and connection into the trace packet, vkreplay has to use it's own anyway
CREATE_TRACE_PACKET(vkCreateXlibSurfaceKHR,
sizeof(VkSurfaceKHR) + sizeof(VkAllocationCallbacks) + sizeof(VkXlibSurfaceCreateInfoKHR));
result = mid(instance)->instTable.CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
pPacket = interpret_body_as_vkCreateXlibSurfaceKHR(pHeader);
pPacket->instance = instance;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkXlibSurfaceCreateInfoKHR), pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSurface), sizeof(VkSurfaceKHR), pSurface);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSurface));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_SurfaceKHR_object(*pSurface);
info.belongsToInstance = instance;
info.ObjectInfo.SurfaceKHR.pCreatePacket = trim::copy_packet(pHeader);
if (pAllocator != NULL) {
info.ObjectInfo.SurfaceKHR.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
VKTRACER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL __HOOKED_vkGetPhysicalDeviceXlibPresentationSupportKHR(
VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID) {
vktrace_trace_packet_header* pHeader;
VkBool32 result;
packet_vkGetPhysicalDeviceXlibPresentationSupportKHR* pPacket = NULL;
// don't bother with copying the actual xlib visual_id and connection into the trace packet, vkreplay has to use it's own anyway
CREATE_TRACE_PACKET(vkGetPhysicalDeviceXlibPresentationSupportKHR, 0);
result =
mid(physicalDevice)->instTable.GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, dpy, visualID);
pPacket = interpret_body_as_vkGetPhysicalDeviceXlibPresentationSupportKHR(pHeader);
pPacket->physicalDevice = physicalDevice;
pPacket->dpy = dpy;
pPacket->queueFamilyIndex = queueFamilyIndex;
pPacket->visualID = visualID;
pPacket->result = result;
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkCreateAndroidSurfaceKHR(VkInstance instance,
const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface) {
vktrace_trace_packet_header* pHeader;
VkResult result;
packet_vkCreateAndroidSurfaceKHR* pPacket = NULL;
// don't bother with copying the actual native window into the trace packet, vkreplay has to use it's own anyway
CREATE_TRACE_PACKET(vkCreateAndroidSurfaceKHR,
sizeof(VkSurfaceKHR) + sizeof(VkAllocationCallbacks) + sizeof(VkAndroidSurfaceCreateInfoKHR));
result = mid(instance)->instTable.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
pPacket = interpret_body_as_vkCreateAndroidSurfaceKHR(pHeader);
pPacket->instance = instance;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCreateInfo), sizeof(VkAndroidSurfaceCreateInfoKHR),
pCreateInfo);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pAllocator), sizeof(VkAllocationCallbacks), NULL);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSurface), sizeof(VkSurfaceKHR), pSurface);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pCreateInfo));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pAllocator));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSurface));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
trim::ObjectInfo& info = trim::add_SurfaceKHR_object(*pSurface);
info.belongsToInstance = instance;
info.ObjectInfo.SurfaceKHR.pCreatePacket = trim::copy_packet(pHeader);
if (pAllocator != NULL) {
info.ObjectInfo.SurfaceKHR.pAllocator = pAllocator;
trim::add_Allocator(pAllocator);
}
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
#endif
// TODO Wayland and Mir support
/* TODO: Probably want to make this manual to get the result of the boolean and then check it on replay
VKTRACER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL __HOOKED_vkGetPhysicalDeviceSurfaceSupportKHR(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
const VkSurfaceDescriptionKHR* pSurfaceDescription,
VkBool32* pSupported)
{
VkResult result;
vktrace_trace_packet_header* pHeader;
packet_vkGetPhysicalDeviceSurfaceSupportKHR* pPacket = NULL;
CREATE_TRACE_PACKET(vkGetPhysicalDeviceSurfaceSupportKHR, sizeof(VkSurfaceDescriptionKHR) + sizeof(VkBool32));
result = mid(physicalDevice)->instTable.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex,
pSurfaceDescription, pSupported);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkGetPhysicalDeviceSurfaceSupportKHR(pHeader);
pPacket->physicalDevice = physicalDevice;
pPacket->queueFamilyIndex = queueFamilyIndex;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSurfaceDescription), sizeof(VkSurfaceDescriptionKHR),
pSurfaceDescription);
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSupported), sizeof(VkBool32), pSupported);
pPacket->result = result;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSurfaceDescription));
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pSupported));
if (!g_trimEnabled)
{
FINISH_TRACE_PACKET();
}
else
{
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim)
{
trim::write_packet(pHeader);
}
else
{
vktrace_delete_trace_packet(&pHeader);
}
}
return result;
}
*/
static inline PFN_vkVoidFunction layer_intercept_proc(const char* name) {
if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
name += 2;
if (!strcmp(name, "CreateDevice")) return (PFN_vkVoidFunction)__HOOKED_vkCreateDevice;
if (!strcmp(name, "DestroyDevice")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyDevice;
if (!strcmp(name, "GetDeviceQueue")) return (PFN_vkVoidFunction)__HOOKED_vkGetDeviceQueue;
if (!strcmp(name, "QueueSubmit")) return (PFN_vkVoidFunction)__HOOKED_vkQueueSubmit;
if (!strcmp(name, "QueueWaitIdle")) return (PFN_vkVoidFunction)__HOOKED_vkQueueWaitIdle;
if (!strcmp(name, "DeviceWaitIdle")) return (PFN_vkVoidFunction)__HOOKED_vkDeviceWaitIdle;
if (!strcmp(name, "AllocateMemory")) return (PFN_vkVoidFunction)__HOOKED_vkAllocateMemory;
if (!strcmp(name, "FreeMemory")) return (PFN_vkVoidFunction)__HOOKED_vkFreeMemory;
if (!strcmp(name, "MapMemory")) return (PFN_vkVoidFunction)__HOOKED_vkMapMemory;
if (!strcmp(name, "UnmapMemory")) return (PFN_vkVoidFunction)__HOOKED_vkUnmapMemory;
if (!strcmp(name, "FlushMappedMemoryRanges")) return (PFN_vkVoidFunction)__HOOKED_vkFlushMappedMemoryRanges;
if (!strcmp(name, "InvalidateMappedMemoryRanges")) return (PFN_vkVoidFunction)__HOOKED_vkInvalidateMappedMemoryRanges;
if (!strcmp(name, "GetDeviceMemoryCommitment")) return (PFN_vkVoidFunction)__HOOKED_vkGetDeviceMemoryCommitment;
if (!strcmp(name, "BindBufferMemory")) return (PFN_vkVoidFunction)__HOOKED_vkBindBufferMemory;
if (!strcmp(name, "BindImageMemory")) return (PFN_vkVoidFunction)__HOOKED_vkBindImageMemory;
if (!strcmp(name, "GetBufferMemoryRequirements")) return (PFN_vkVoidFunction)__HOOKED_vkGetBufferMemoryRequirements;
if (!strcmp(name, "GetImageMemoryRequirements")) return (PFN_vkVoidFunction)__HOOKED_vkGetImageMemoryRequirements;
if (!strcmp(name, "GetImageSparseMemoryRequirements")) return (PFN_vkVoidFunction)__HOOKED_vkGetImageSparseMemoryRequirements;
if (!strcmp(name, "GetPhysicalDeviceSparseImageFormatProperties"))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceSparseImageFormatProperties;
if (!strcmp(name, "QueueBindSparse")) return (PFN_vkVoidFunction)__HOOKED_vkQueueBindSparse;
if (!strcmp(name, "CreateFence")) return (PFN_vkVoidFunction)__HOOKED_vkCreateFence;
if (!strcmp(name, "DestroyFence")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyFence;
if (!strcmp(name, "ResetFences")) return (PFN_vkVoidFunction)__HOOKED_vkResetFences;
if (!strcmp(name, "GetFenceStatus")) return (PFN_vkVoidFunction)__HOOKED_vkGetFenceStatus;
if (!strcmp(name, "WaitForFences")) return (PFN_vkVoidFunction)__HOOKED_vkWaitForFences;
if (!strcmp(name, "CreateSemaphore")) return (PFN_vkVoidFunction)__HOOKED_vkCreateSemaphore;
if (!strcmp(name, "DestroySemaphore")) return (PFN_vkVoidFunction)__HOOKED_vkDestroySemaphore;
if (!strcmp(name, "CreateEvent")) return (PFN_vkVoidFunction)__HOOKED_vkCreateEvent;
if (!strcmp(name, "DestroyEvent")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyEvent;
if (!strcmp(name, "GetEventStatus")) return (PFN_vkVoidFunction)__HOOKED_vkGetEventStatus;
if (!strcmp(name, "SetEvent")) return (PFN_vkVoidFunction)__HOOKED_vkSetEvent;
if (!strcmp(name, "ResetEvent")) return (PFN_vkVoidFunction)__HOOKED_vkResetEvent;
if (!strcmp(name, "CreateQueryPool")) return (PFN_vkVoidFunction)__HOOKED_vkCreateQueryPool;
if (!strcmp(name, "DestroyQueryPool")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyQueryPool;
if (!strcmp(name, "GetQueryPoolResults")) return (PFN_vkVoidFunction)__HOOKED_vkGetQueryPoolResults;
if (!strcmp(name, "CreateBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkCreateBuffer;
if (!strcmp(name, "DestroyBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyBuffer;
if (!strcmp(name, "CreateBufferView")) return (PFN_vkVoidFunction)__HOOKED_vkCreateBufferView;
if (!strcmp(name, "DestroyBufferView")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyBufferView;
if (!strcmp(name, "CreateImage")) return (PFN_vkVoidFunction)__HOOKED_vkCreateImage;
if (!strcmp(name, "DestroyImage")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyImage;
if (!strcmp(name, "GetImageSubresourceLayout")) return (PFN_vkVoidFunction)__HOOKED_vkGetImageSubresourceLayout;
if (!strcmp(name, "CreateImageView")) return (PFN_vkVoidFunction)__HOOKED_vkCreateImageView;
if (!strcmp(name, "DestroyImageView")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyImageView;
if (!strcmp(name, "CreateShaderModule")) return (PFN_vkVoidFunction)__HOOKED_vkCreateShaderModule;
if (!strcmp(name, "DestroyShaderModule")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyShaderModule;
if (!strcmp(name, "CreatePipelineCache")) return (PFN_vkVoidFunction)__HOOKED_vkCreatePipelineCache;
if (!strcmp(name, "DestroyPipelineCache")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyPipelineCache;
if (!strcmp(name, "GetPipelineCacheData")) return (PFN_vkVoidFunction)__HOOKED_vkGetPipelineCacheData;
if (!strcmp(name, "MergePipelineCaches")) return (PFN_vkVoidFunction)__HOOKED_vkMergePipelineCaches;
if (!strcmp(name, "CreateGraphicsPipelines")) return (PFN_vkVoidFunction)__HOOKED_vkCreateGraphicsPipelines;
if (!strcmp(name, "CreateComputePipelines")) return (PFN_vkVoidFunction)__HOOKED_vkCreateComputePipelines;
if (!strcmp(name, "DestroyPipeline")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyPipeline;
if (!strcmp(name, "CreatePipelineLayout")) return (PFN_vkVoidFunction)__HOOKED_vkCreatePipelineLayout;
if (!strcmp(name, "DestroyPipelineLayout")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyPipelineLayout;
if (!strcmp(name, "CreateSampler")) return (PFN_vkVoidFunction)__HOOKED_vkCreateSampler;
if (!strcmp(name, "DestroySampler")) return (PFN_vkVoidFunction)__HOOKED_vkDestroySampler;
if (!strcmp(name, "CreateDescriptorSetLayout")) return (PFN_vkVoidFunction)__HOOKED_vkCreateDescriptorSetLayout;
if (!strcmp(name, "DestroyDescriptorSetLayout")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyDescriptorSetLayout;
if (!strcmp(name, "CreateDescriptorPool")) return (PFN_vkVoidFunction)__HOOKED_vkCreateDescriptorPool;
if (!strcmp(name, "DestroyDescriptorPool")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyDescriptorPool;
if (!strcmp(name, "ResetDescriptorPool")) return (PFN_vkVoidFunction)__HOOKED_vkResetDescriptorPool;
if (!strcmp(name, "AllocateDescriptorSets")) return (PFN_vkVoidFunction)__HOOKED_vkAllocateDescriptorSets;
if (!strcmp(name, "FreeDescriptorSets")) return (PFN_vkVoidFunction)__HOOKED_vkFreeDescriptorSets;
if (!strcmp(name, "UpdateDescriptorSets")) return (PFN_vkVoidFunction)__HOOKED_vkUpdateDescriptorSets;
if (!strcmp(name, "CreateCommandPool")) return (PFN_vkVoidFunction)__HOOKED_vkCreateCommandPool;
if (!strcmp(name, "DestroyCommandPool")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyCommandPool;
if (!strcmp(name, "ResetCommandPool")) return (PFN_vkVoidFunction)__HOOKED_vkResetCommandPool;
if (!strcmp(name, "AllocateCommandBuffers")) return (PFN_vkVoidFunction)__HOOKED_vkAllocateCommandBuffers;
if (!strcmp(name, "FreeCommandBuffers")) return (PFN_vkVoidFunction)__HOOKED_vkFreeCommandBuffers;
if (!strcmp(name, "BeginCommandBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkBeginCommandBuffer;
if (!strcmp(name, "EndCommandBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkEndCommandBuffer;
if (!strcmp(name, "ResetCommandBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkResetCommandBuffer;
if (!strcmp(name, "CmdBindPipeline")) return (PFN_vkVoidFunction)__HOOKED_vkCmdBindPipeline;
if (!strcmp(name, "CmdSetViewport")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetViewport;
if (!strcmp(name, "CmdSetScissor")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetScissor;
if (!strcmp(name, "CmdSetLineWidth")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetLineWidth;
if (!strcmp(name, "CmdSetDepthBias")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetDepthBias;
if (!strcmp(name, "CmdSetBlendConstants")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetBlendConstants;
if (!strcmp(name, "CmdSetDepthBounds")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetDepthBounds;
if (!strcmp(name, "CmdSetStencilCompareMask")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetStencilCompareMask;
if (!strcmp(name, "CmdSetStencilWriteMask")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetStencilWriteMask;
if (!strcmp(name, "CmdSetStencilReference")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetStencilReference;
if (!strcmp(name, "CmdBindDescriptorSets")) return (PFN_vkVoidFunction)__HOOKED_vkCmdBindDescriptorSets;
if (!strcmp(name, "CmdBindIndexBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkCmdBindIndexBuffer;
if (!strcmp(name, "CmdBindVertexBuffers")) return (PFN_vkVoidFunction)__HOOKED_vkCmdBindVertexBuffers;
if (!strcmp(name, "CmdDraw")) return (PFN_vkVoidFunction)__HOOKED_vkCmdDraw;
if (!strcmp(name, "CmdDrawIndexed")) return (PFN_vkVoidFunction)__HOOKED_vkCmdDrawIndexed;
if (!strcmp(name, "CmdDrawIndirect")) return (PFN_vkVoidFunction)__HOOKED_vkCmdDrawIndirect;
if (!strcmp(name, "CmdDrawIndexedIndirect")) return (PFN_vkVoidFunction)__HOOKED_vkCmdDrawIndexedIndirect;
if (!strcmp(name, "CmdDispatch")) return (PFN_vkVoidFunction)__HOOKED_vkCmdDispatch;
if (!strcmp(name, "CmdDispatchIndirect")) return (PFN_vkVoidFunction)__HOOKED_vkCmdDispatchIndirect;
if (!strcmp(name, "CmdCopyBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkCmdCopyBuffer;
if (!strcmp(name, "CmdCopyImage")) return (PFN_vkVoidFunction)__HOOKED_vkCmdCopyImage;
if (!strcmp(name, "CmdBlitImage")) return (PFN_vkVoidFunction)__HOOKED_vkCmdBlitImage;
if (!strcmp(name, "CmdCopyBufferToImage")) return (PFN_vkVoidFunction)__HOOKED_vkCmdCopyBufferToImage;
if (!strcmp(name, "CmdCopyImageToBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkCmdCopyImageToBuffer;
if (!strcmp(name, "CmdUpdateBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkCmdUpdateBuffer;
if (!strcmp(name, "CmdFillBuffer")) return (PFN_vkVoidFunction)__HOOKED_vkCmdFillBuffer;
if (!strcmp(name, "CmdClearColorImage")) return (PFN_vkVoidFunction)__HOOKED_vkCmdClearColorImage;
if (!strcmp(name, "CmdClearDepthStencilImage")) return (PFN_vkVoidFunction)__HOOKED_vkCmdClearDepthStencilImage;
if (!strcmp(name, "CmdClearAttachments")) return (PFN_vkVoidFunction)__HOOKED_vkCmdClearAttachments;
if (!strcmp(name, "CmdResolveImage")) return (PFN_vkVoidFunction)__HOOKED_vkCmdResolveImage;
if (!strcmp(name, "CmdSetEvent")) return (PFN_vkVoidFunction)__HOOKED_vkCmdSetEvent;
if (!strcmp(name, "CmdResetEvent")) return (PFN_vkVoidFunction)__HOOKED_vkCmdResetEvent;
if (!strcmp(name, "CmdWaitEvents")) return (PFN_vkVoidFunction)__HOOKED_vkCmdWaitEvents;
if (!strcmp(name, "CmdPipelineBarrier")) return (PFN_vkVoidFunction)__HOOKED_vkCmdPipelineBarrier;
if (!strcmp(name, "CmdBeginQuery")) return (PFN_vkVoidFunction)__HOOKED_vkCmdBeginQuery;
if (!strcmp(name, "CmdEndQuery")) return (PFN_vkVoidFunction)__HOOKED_vkCmdEndQuery;
if (!strcmp(name, "CmdResetQueryPool")) return (PFN_vkVoidFunction)__HOOKED_vkCmdResetQueryPool;
if (!strcmp(name, "CmdWriteTimestamp")) return (PFN_vkVoidFunction)__HOOKED_vkCmdWriteTimestamp;
if (!strcmp(name, "CmdCopyQueryPoolResults")) return (PFN_vkVoidFunction)__HOOKED_vkCmdCopyQueryPoolResults;
if (!strcmp(name, "CreateFramebuffer")) return (PFN_vkVoidFunction)__HOOKED_vkCreateFramebuffer;
if (!strcmp(name, "DestroyFramebuffer")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyFramebuffer;
if (!strcmp(name, "CreateRenderPass")) return (PFN_vkVoidFunction)__HOOKED_vkCreateRenderPass;
if (!strcmp(name, "DestroyRenderPass")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyRenderPass;
if (!strcmp(name, "GetRenderAreaGranularity")) return (PFN_vkVoidFunction)__HOOKED_vkGetRenderAreaGranularity;
if (!strcmp(name, "CmdBeginRenderPass")) return (PFN_vkVoidFunction)__HOOKED_vkCmdBeginRenderPass;
if (!strcmp(name, "CmdNextSubpass")) return (PFN_vkVoidFunction)__HOOKED_vkCmdNextSubpass;
if (!strcmp(name, "CmdPushConstants")) return (PFN_vkVoidFunction)__HOOKED_vkCmdPushConstants;
if (!strcmp(name, "CmdEndRenderPass")) return (PFN_vkVoidFunction)__HOOKED_vkCmdEndRenderPass;
if (!strcmp(name, "CmdExecuteCommands")) return (PFN_vkVoidFunction)__HOOKED_vkCmdExecuteCommands;
return NULL;
}
static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char* name) {
if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
name += 2;
if (!strcmp(name, "CreateDevice")) return (PFN_vkVoidFunction)__HOOKED_vkCreateDevice;
if (!strcmp(name, "CreateInstance")) return (PFN_vkVoidFunction)__HOOKED_vkCreateInstance;
if (!strcmp(name, "DestroyInstance")) return (PFN_vkVoidFunction)__HOOKED_vkDestroyInstance;
if (!strcmp(name, "EnumeratePhysicalDevices")) return (PFN_vkVoidFunction)__HOOKED_vkEnumeratePhysicalDevices;
if (!strcmp(name, "GetPhysicalDeviceFeatures")) return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceFeatures;
if (!strcmp(name, "GetPhysicalDeviceFormatProperties")) return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceFormatProperties;
if (!strcmp(name, "GetPhysicalDeviceImageFormatProperties"))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceImageFormatProperties;
if (!strcmp(name, "GetPhysicalDeviceSparseImageFormatProperties"))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceSparseImageFormatProperties;
if (!strcmp(name, "GetPhysicalDeviceProperties")) return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceProperties;
if (!strcmp(name, "GetPhysicalDeviceQueueFamilyProperties"))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceQueueFamilyProperties;
if (!strcmp(name, "GetPhysicalDeviceMemoryProperties")) return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceMemoryProperties;
if (!strcmp(name, "EnumerateDeviceLayerProperties")) return (PFN_vkVoidFunction)__HOOKED_vkEnumerateDeviceLayerProperties;
if (!strcmp(name, "EnumerateDeviceExtensionProperties"))
return (PFN_vkVoidFunction)__HOOKED_vkEnumerateDeviceExtensionProperties;
return NULL;
}
/**
* Want trace packets created for GetDeviceProcAddr that is app initiated
* but not for loader initiated calls to GDPA. Thus need two versions of GDPA.
*/
VKTRACER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vktraceGetDeviceProcAddr(VkDevice device, const char* funcName) {
PFN_vkVoidFunction addr;
vktrace_trace_packet_header* pHeader;
packet_vkGetDeviceProcAddr* pPacket = NULL;
CREATE_TRACE_PACKET(vkGetDeviceProcAddr, ((funcName != NULL) ? ROUNDUP_TO_4(strlen(funcName) + 1) : 0));
addr = __HOOKED_vkGetDeviceProcAddr(device, funcName);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkGetDeviceProcAddr(pHeader);
pPacket->device = device;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pName),
((funcName != NULL) ? ROUNDUP_TO_4(strlen(funcName) + 1) : 0), funcName);
pPacket->result = addr;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pName));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return addr;
}
/* GDPA with no trace packet creation */
VKTRACER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL __HOOKED_vkGetDeviceProcAddr(VkDevice device, const char* funcName) {
if (!strcmp("vkGetDeviceProcAddr", funcName)) {
if (gMessageStream != NULL) {
return (PFN_vkVoidFunction)vktraceGetDeviceProcAddr;
} else {
return (PFN_vkVoidFunction)__HOOKED_vkGetDeviceProcAddr;
}
}
layer_device_data* devData = mdd(device);
if (gMessageStream != NULL) {
PFN_vkVoidFunction addr;
addr = layer_intercept_proc(funcName);
if (addr) return addr;
if (devData->KHRDeviceSwapchainEnabled) {
if (!strcmp("vkCreateSwapchainKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkCreateSwapchainKHR;
if (!strcmp("vkDestroySwapchainKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkDestroySwapchainKHR;
if (!strcmp("vkGetSwapchainImagesKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkGetSwapchainImagesKHR;
if (!strcmp("vkAcquireNextImageKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkAcquireNextImageKHR;
if (!strcmp("vkQueuePresentKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkQueuePresentKHR;
}
}
if (device == VK_NULL_HANDLE) {
return NULL;
}
VkLayerDispatchTable* pDisp = &devData->devTable;
if (pDisp->GetDeviceProcAddr == NULL) return NULL;
return pDisp->GetDeviceProcAddr(device, funcName);
}
/**
* Want trace packets created for GetInstanceProcAddr that is app initiated
* but not for loader initiated calls to GIPA. Thus need two versions of GIPA.
*/
VKTRACER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vktraceGetInstanceProcAddr(VkInstance instance, const char* funcName) {
PFN_vkVoidFunction addr;
vktrace_trace_packet_header* pHeader;
packet_vkGetInstanceProcAddr* pPacket = NULL;
// assert(strcmp("vkGetInstanceProcAddr", funcName));
CREATE_TRACE_PACKET(vkGetInstanceProcAddr, ((funcName != NULL) ? ROUNDUP_TO_4(strlen(funcName) + 1) : 0));
addr = __HOOKED_vkGetInstanceProcAddr(instance, funcName);
vktrace_set_packet_entrypoint_end_time(pHeader);
pPacket = interpret_body_as_vkGetInstanceProcAddr(pHeader);
pPacket->instance = instance;
vktrace_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pName),
((funcName != NULL) ? ROUNDUP_TO_4(strlen(funcName) + 1) : 0), funcName);
pPacket->result = addr;
vktrace_finalize_buffer_address(pHeader, (void**)&(pPacket->pName));
if (!g_trimEnabled) {
FINISH_TRACE_PACKET();
} else {
vktrace_finalize_trace_packet(pHeader);
if (g_trimIsInTrim) {
trim::write_packet(pHeader);
} else {
vktrace_delete_trace_packet(&pHeader);
}
}
return addr;
}
/* GIPA with no trace packet creation */
VKTRACER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL __HOOKED_vkGetInstanceProcAddr(VkInstance instance, const char* funcName) {
PFN_vkVoidFunction addr;
layer_instance_data* instData;
vktrace_platform_thread_once((void*)&gInitOnce, InitTracer);
if (!strcmp("vkGetInstanceProcAddr", funcName)) {
if (gMessageStream != NULL) {
return (PFN_vkVoidFunction)vktraceGetInstanceProcAddr;
} else {
return (PFN_vkVoidFunction)__HOOKED_vkGetInstanceProcAddr;
}
}
if (gMessageStream != NULL) {
addr = layer_intercept_instance_proc(funcName);
if (addr) return addr;
if (instance == VK_NULL_HANDLE) {
return NULL;
}
instData = mid(instance);
if (instData->LunargDebugReportEnabled) {
if (!strcmp("vkCreateDebugReportCallbackEXT", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkCreateDebugReportCallbackEXT;
if (!strcmp("vkDestroyDebugReportCallbackEXT", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkDestroyDebugReportCallbackEXT;
}
if (instData->KHRSurfaceEnabled) {
if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceSurfaceSupportKHR;
if (!strcmp("vkDestroySurfaceKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkDestroySurfaceKHR;
if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceSurfaceFormatsKHR;
if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceSurfacePresentModesKHR;
}
#ifdef VK_USE_PLATFORM_XLIB_KHR
if (instData->KHRXlibSurfaceEnabled) {
if (!strcmp("vkCreateXlibSurfaceKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkCreateXlibSurfaceKHR;
if (!strcmp("vkGetPhysicalDeviceXlibPresentationSupportKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceXlibPresentationSupportKHR;
}
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
if (instData->KHRXcbSurfaceEnabled) {
if (!strcmp("vkCreateXcbSurfaceKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkCreateXcbSurfaceKHR;
if (!strcmp("vkGetPhysicalDeviceXcbPresentationSupportKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceXcbPresentationSupportKHR;
}
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
if (instData->KHRWaylandSurfaceEnabled) {
if (!strcmp("vkCreateWaylandSurfaceKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkCreateWaylandSurfaceKHR;
if (!strcmp("vkGetPhysicalDeviceWaylandPresentationSupportKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceWaylandPresentationSupportKHR;
}
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
if (instData->KHRMirSurfaceEnabled) {
if (!strcmp("vkCreateMirSurfaceKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkCreateMirSurfaceKHR;
if (!strcmp("vkGetPhysicalDeviceMirPresentationSupportKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceMirPresentationSupportKHR;
}
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
if (instData->KHRWin32SurfaceEnabled) {
if (!strcmp("vkCreateWin32SurfaceKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkCreateWin32SurfaceKHR;
if (!strcmp("vkGetPhysicalDeviceWin32PresentationSupportKHR", funcName))
return (PFN_vkVoidFunction)__HOOKED_vkGetPhysicalDeviceWin32PresentationSupportKHR;
}
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
if (instData->KHRAndroidSurfaceEnabled) {
if (!strcmp("vkCreateAndroidSurfaceKHR", funcName)) return (PFN_vkVoidFunction)__HOOKED_vkCreateAndroidSurfaceKHR;
}
#endif
} else {
if (instance == VK_NULL_HANDLE) {
return NULL;
}
instData = mid(instance);
}
VkLayerInstanceDispatchTable* pTable = &instData->instTable;
if (pTable->GetInstanceProcAddr == NULL) return NULL;
return pTable->GetInstanceProcAddr(instance, funcName);
}
static const VkLayerProperties layerProps = {
"VK_LAYER_LUNARG_vktrace", VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION), 1, "LunarG tracing layer",
};
template <typename T>
VkResult EnumerateProperties(uint32_t src_count, const T* src_props, uint32_t* dst_count, T* dst_props) {
if (!dst_props || !src_props) {
*dst_count = src_count;
return VK_SUCCESS;
}
uint32_t copy_count = (*dst_count < src_count) ? *dst_count : src_count;
memcpy(dst_props, src_props, sizeof(T) * copy_count);
*dst_count = copy_count;
return (copy_count == src_count) ? VK_SUCCESS : VK_INCOMPLETE;
}
// LoaderLayerInterface V0
// https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
VkLayerProperties* pProperties) {
return EnumerateProperties(1, &layerProps, pPropertyCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (pLayerName && !strcmp(pLayerName, layerProps.layerName))
return EnumerateProperties(0, (VkExtensionProperties*)nullptr, pPropertyCount, pProperties);
return VK_ERROR_LAYER_NOT_PRESENT;
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
uint32_t* pPropertyCount,
VkLayerProperties* pProperties) {
return EnumerateProperties(1, &layerProps, pPropertyCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (pLayerName && !strcmp(pLayerName, layerProps.layerName))
return EnumerateProperties(0, (VkExtensionProperties*)nullptr, pPropertyCount, pProperties);
return VK_ERROR_LAYER_NOT_PRESENT;
}
VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL VK_LAYER_LUNARG_vktraceGetInstanceProcAddr(VkInstance instance,
const char* funcName) {
return __HOOKED_vkGetInstanceProcAddr(instance, funcName);
}
VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL VK_LAYER_LUNARG_vktraceGetDeviceProcAddr(VkDevice device,
const char* funcName) {
return __HOOKED_vkGetDeviceProcAddr(device, funcName);
}