blob: 47c263fb438f210b1cb084114b5425483bf739a0 [file] [log] [blame]
/*
* Vulkan
*
* Copyright (C) 2014 LunarG, Inc.
* Copyright (C) 2015 Valve Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "vulkan.h"
#include "glv_platform.h"
#include "glv_common.h"
#include "glvtrace_vk_helpers.h"
#include "glvtrace_vk_vk.h"
#include "glvtrace_vk_vkdbg.h"
#include "glvtrace_vk_vkwsix11ext.h"
#include "glv_interconnect.h"
#include "glv_filelike.h"
#ifdef WIN32
#include "mhook/mhook-lib/mhook.h"
#endif
#include "glv_trace_packet_utils.h"
#include <stdio.h>
// declared as extern in glvtrace_vk_helpers.h
GLV_CRITICAL_SECTION g_memInfoLock;
VKMemInfo g_memInfo = {0, NULL, NULL, 0};
GLVTRACER_EXPORT VkResult VKAPI __HOOKED_vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
VkInstance* pInstance)
{
glv_trace_packet_header* pHeader;
VkResult result;
struct_vkCreateInstance* pPacket = NULL;
uint64_t startTime;
glv_platform_thread_once(&gInitOnce, InitTracer);
SEND_ENTRYPOINT_ID(vkCreateInstance);
if (real_vkCreateInstance == vkCreateInstance)
{
glv_platform_get_next_lib_sym((void **) &real_vkCreateInstance,"vkCreateInstance");
}
startTime = glv_get_time();
result = real_vkCreateInstance(pCreateInfo, pInstance);
CREATE_TRACE_PACKET(vkCreateInstance, sizeof(VkInstance) + get_struct_chain_size((void*)pCreateInfo));
pHeader->entrypoint_begin_time = startTime;
if (isHooked == FALSE) {
AttachHooks();
AttachHooks_vkdbg();
AttachHooks_vkwsix11ext();
}
pPacket = interpret_body_as_vkCreateInstance(pHeader);
add_VK_INSTANCE_CREATE_INFO_to_packet(pHeader, (VkInstanceCreateInfo**)&(pPacket->pCreateInfo), pCreateInfo);
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pInstance), sizeof(VkInstance), pInstance);
pPacket->result = result;
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pInstance));
FINISH_TRACE_PACKET();
return result;
}
GLVTRACER_EXPORT VkResult VKAPI __HOOKED_vkEnumerateLayers(
VK_PHYSICAL_GPU gpu,
size_t maxLayerCount,
size_t maxStringSize,
size_t* pOutLayerCount,
char* const* pOutLayers,
void* pReserved)
{
glv_trace_packet_header* pHeader;
VkResult result;
struct_vkEnumerateLayers* pPacket = NULL;
uint64_t startTime;
SEND_ENTRYPOINT_ID(vkEnumerateLayers);
startTime = glv_get_time();
result = real_vkEnumerateLayers(gpu, maxLayerCount, maxStringSize, pOutLayerCount, pOutLayers, pReserved);
size_t totStringSize = 0;
uint32_t i = 0;
for (i = 0; i < *pOutLayerCount; i++) {
totStringSize += (pOutLayers[i] != NULL) ? strlen(pOutLayers[i]) + 1: 0;
}
CREATE_TRACE_PACKET(vkEnumerateLayers, totStringSize + sizeof(size_t));
pHeader->entrypoint_begin_time = startTime;
pPacket = interpret_body_as_vkEnumerateLayers(pHeader);
pPacket->gpu = gpu;
pPacket->maxLayerCount = maxLayerCount;
pPacket->maxStringSize = maxStringSize;
pPacket->pReserved = pReserved;
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pOutLayerCount), sizeof(size_t), pOutLayerCount);
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pOutLayerCount));
for (i = 0; i < *pOutLayerCount; i++) {
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pOutLayers[i]), ((pOutLayers[i] != NULL) ? strlen(pOutLayers[i]) + 1 : 0), pOutLayers[i]);
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pOutLayers[i]));
}
pPacket->result = result;
FINISH_TRACE_PACKET();
return result;
}
GLVTRACER_EXPORT VkResult VKAPI __HOOKED_vkEnumerateGpus(
VkInstance instance,
uint32_t maxGpus,
uint32_t* pGpuCount,
VK_PHYSICAL_GPU* pGpus)
{
glv_trace_packet_header* pHeader;
VkResult result;
struct_vkEnumerateGpus* pPacket = NULL;
uint64_t startTime;
SEND_ENTRYPOINT_ID(vkEnumerateGpus);
startTime = glv_get_time();
result = real_vkEnumerateGpus(instance, maxGpus, pGpuCount, pGpus);
CREATE_TRACE_PACKET(vkEnumerateGpus, sizeof(uint32_t) + ((pGpus && pGpuCount) ? *pGpuCount * sizeof(VK_PHYSICAL_GPU) : 0));
pHeader->entrypoint_begin_time = startTime;
pPacket = interpret_body_as_vkEnumerateGpus(pHeader);
pPacket->instance = instance;
pPacket->maxGpus = maxGpus;
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pGpuCount), sizeof(uint32_t), pGpuCount);
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pGpus), *pGpuCount*sizeof(VK_PHYSICAL_GPU), pGpus);
pPacket->result = result;
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pGpuCount));
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pGpus));
FINISH_TRACE_PACKET();
return result;
}
GLVTRACER_EXPORT VkResult VKAPI __HOOKED_vkAllocDescriptorSets(
VK_DESCRIPTOR_POOL descriptorPool,
VK_DESCRIPTOR_SET_USAGE setUsage,
uint32_t count,
const VK_DESCRIPTOR_SET_LAYOUT* pSetLayouts,
VK_DESCRIPTOR_SET* pDescriptorSets,
uint32_t* pCount)
{
glv_trace_packet_header* pHeader;
VkResult result;
struct_vkAllocDescriptorSets* pPacket = NULL;
uint64_t startTime;
SEND_ENTRYPOINT_ID(vkAllocDescriptorSets);
startTime = glv_get_time();
result = real_vkAllocDescriptorSets(descriptorPool, setUsage, count, pSetLayouts, pDescriptorSets, pCount);
size_t customSize = (*pCount <= 0) ? (sizeof(VK_DESCRIPTOR_SET)) : (*pCount * sizeof(VK_DESCRIPTOR_SET));
CREATE_TRACE_PACKET(vkAllocDescriptorSets, sizeof(VK_DESCRIPTOR_SET_LAYOUT) + customSize + sizeof(uint32_t));
pHeader->entrypoint_begin_time = startTime;
pPacket = interpret_body_as_vkAllocDescriptorSets(pHeader);
pPacket->descriptorPool = descriptorPool;
pPacket->setUsage = setUsage;
pPacket->count = count;
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pSetLayouts), count*sizeof(VK_DESCRIPTOR_SET_LAYOUT), pSetLayouts);
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pDescriptorSets), customSize, pDescriptorSets);
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pCount), sizeof(uint32_t), pCount);
pPacket->result = result;
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pSetLayouts));
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pDescriptorSets));
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pCount));
FINISH_TRACE_PACKET();
return result;
}
GLVTRACER_EXPORT VkResult VKAPI __HOOKED_vkMapMemory(
VK_GPU_MEMORY mem,
VK_FLAGS flags,
void** ppData)
{
glv_trace_packet_header* pHeader;
VkResult result;
struct_vkMapMemory* pPacket = NULL;
CREATE_TRACE_PACKET(vkMapMemory, sizeof(void*));
result = real_vkMapMemory(mem, flags, ppData);
pPacket = interpret_body_as_vkMapMemory(pHeader);
pPacket->mem = mem;
pPacket->flags = flags;
if (ppData != NULL)
{
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->ppData), sizeof(void*), *ppData);
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->ppData));
add_data_to_mem_info(mem, *ppData);
}
pPacket->result = result;
FINISH_TRACE_PACKET();
return result;
}
GLVTRACER_EXPORT VkResult VKAPI __HOOKED_vkUnmapMemory(VK_GPU_MEMORY mem)
{
glv_trace_packet_header* pHeader;
VkResult result;
struct_vkUnmapMemory* pPacket;
VKAllocInfo *entry;
SEND_ENTRYPOINT_PARAMS("vkUnmapMemory(mem %p)\n", mem);
// 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
glv_enter_critical_section(&g_memInfoLock);
entry = find_mem_info_entry(mem);
CREATE_TRACE_PACKET(vkUnmapMemory, (entry) ? entry->size : 0);
pPacket = interpret_body_as_vkUnmapMemory(pHeader);
if (entry)
{
assert(entry->handle == mem);
glv_add_buffer_to_trace_packet(pHeader, (void**) &(pPacket->pData), entry->size, entry->pData);
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pData));
entry->pData = NULL;
} else
{
glv_LogError("Failed to copy app memory into trace packet (idx = %u) on vkUnmapMemory\n", pHeader->global_packet_index);
}
glv_leave_critical_section(&g_memInfoLock);
// glv_LogError("manual address of vkUnmapMemory: %p\n", real_vkUnmapMemory);
result = real_vkUnmapMemory(mem);
pPacket->mem = mem;
pPacket->result = result;
FINISH_TRACE_PACKET();
return result;
}
GLVTRACER_EXPORT void VKAPI __HOOKED_vkCmdWaitEvents(
VK_CMD_BUFFER cmdBuffer,
const VK_EVENT_WAIT_INFO* pWaitInfo)
{
glv_trace_packet_header* pHeader;
struct_vkCmdWaitEvents* pPacket = NULL;
size_t customSize;
uint32_t eventCount = (pWaitInfo != NULL && pWaitInfo->pEvents != NULL) ? pWaitInfo->eventCount : 0;
uint32_t mbCount = (pWaitInfo != NULL && pWaitInfo->ppMemBarriers != NULL) ? pWaitInfo->memBarrierCount : 0;
customSize = (eventCount * sizeof(VK_EVENT)) + mbCount * sizeof(void*) + calculate_memory_barrier_size(mbCount, pWaitInfo->ppMemBarriers);
CREATE_TRACE_PACKET(vkCmdWaitEvents, sizeof(VK_EVENT_WAIT_INFO) + customSize);
real_vkCmdWaitEvents(cmdBuffer, pWaitInfo);
pPacket = interpret_body_as_vkCmdWaitEvents(pHeader);
pPacket->cmdBuffer = cmdBuffer;
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pWaitInfo), sizeof(VK_EVENT_WAIT_INFO), pWaitInfo);
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pWaitInfo->pEvents), eventCount * sizeof(VK_EVENT), pWaitInfo->pEvents);
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pWaitInfo->pEvents));
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pWaitInfo->ppMemBarriers), mbCount * sizeof(void*), pWaitInfo->ppMemBarriers);
uint32_t i, siz;
for (i = 0; i < mbCount; i++) {
VK_MEMORY_BARRIER *pNext = (VK_MEMORY_BARRIER *) pWaitInfo->ppMemBarriers[i];
switch (pNext->sType) {
case VK_STRUCTURE_TYPE_MEMORY_BARRIER:
siz = sizeof(VK_MEMORY_BARRIER);
break;
case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER:
siz = sizeof(VK_BUFFER_MEMORY_BARRIER);
break;
case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER:
siz = sizeof(VK_IMAGE_MEMORY_BARRIER);
break;
default:
assert(0);
siz = 0;
break;
}
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pWaitInfo->ppMemBarriers[i]), siz, pWaitInfo->ppMemBarriers[i]);
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pWaitInfo->ppMemBarriers[i]));
}
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pWaitInfo->ppMemBarriers));
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pWaitInfo));
FINISH_TRACE_PACKET();
}
GLVTRACER_EXPORT void VKAPI __HOOKED_vkCmdPipelineBarrier(
VK_CMD_BUFFER cmdBuffer,
const VK_PIPELINE_BARRIER* pBarrier)
{
glv_trace_packet_header* pHeader;
struct_vkCmdPipelineBarrier* pPacket = NULL;
size_t customSize;
uint32_t eventCount = (pBarrier != NULL && pBarrier->pEvents != NULL) ? pBarrier->eventCount : 0;
uint32_t mbCount = (pBarrier != NULL && pBarrier->ppMemBarriers != NULL) ? pBarrier->memBarrierCount : 0;
customSize = (eventCount * sizeof(VK_PIPE_EVENT)) + mbCount * sizeof(void*) + calculate_memory_barrier_size(mbCount, pBarrier->ppMemBarriers);
CREATE_TRACE_PACKET(vkCmdPipelineBarrier, sizeof(VK_PIPELINE_BARRIER) + customSize);
real_vkCmdPipelineBarrier(cmdBuffer, pBarrier);
pPacket = interpret_body_as_vkCmdPipelineBarrier(pHeader);
pPacket->cmdBuffer = cmdBuffer;
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBarrier), sizeof(VK_PIPELINE_BARRIER), pBarrier);
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBarrier->pEvents), eventCount * sizeof(VK_PIPE_EVENT), pBarrier->pEvents);
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pBarrier->pEvents));
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBarrier->ppMemBarriers), mbCount * sizeof(void*), pBarrier->ppMemBarriers);
uint32_t i, siz;
for (i = 0; i < mbCount; i++) {
VK_MEMORY_BARRIER *pNext = (VK_MEMORY_BARRIER *) pBarrier->ppMemBarriers[i];
switch (pNext->sType) {
case VK_STRUCTURE_TYPE_MEMORY_BARRIER:
siz = sizeof(VK_MEMORY_BARRIER);
break;
case VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER:
siz = sizeof(VK_BUFFER_MEMORY_BARRIER);
break;
case VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER:
siz = sizeof(VK_IMAGE_MEMORY_BARRIER);
break;
default:
assert(0);
siz = 0;
break;
}
glv_add_buffer_to_trace_packet(pHeader, (void**)&(pPacket->pBarrier->ppMemBarriers[i]), siz, pBarrier->ppMemBarriers[i]);
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pBarrier->ppMemBarriers[i]));
}
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pBarrier->ppMemBarriers));
glv_finalize_buffer_address(pHeader, (void**)&(pPacket->pBarrier));
FINISH_TRACE_PACKET();
}