Create a WrappedVulkan per VkInstance and indirect to find it in layer

This commit is contained in:
baldurk
2015-10-23 15:13:28 +02:00
parent 24aa8b3daf
commit d38741e9ab
5 changed files with 61 additions and 42 deletions
+4 -1
View File
@@ -41,9 +41,12 @@ void InitDeviceReplayTables(VkDevice device);
VkLayerDispatchTable *GetDeviceDispatchTable(void *device);
VkLayerInstanceDispatchTable *GetInstanceDispatchTable(void *instance);
class WrappedVulkan;
template<typename parenttype, typename wrappedtype>
void SetDispatchTable(bool writing, parenttype parent, wrappedtype *wrapped)
void SetDispatchTable(bool writing, parenttype parent, WrappedVulkan *core, wrappedtype *wrapped)
{
wrapped->core = core;
if(writing)
{
wrapped->table = wrappedtype::UseInstanceDispatchTable
@@ -179,8 +179,6 @@
HookInit(QueuePresentKHR);
#define DefineHooks() \
HookDefine2(VkResult, vkCreateInstance, const VkInstanceCreateInfo*, pCreateInfo, VkInstance*, pInstance); \
HookDefine1(void, vkDestroyInstance, VkInstance, instance); \
HookDefine3(VkResult, vkEnumeratePhysicalDevices, VkInstance, instance, uint32_t*, pPhysicalDeviceCount, VkPhysicalDevice*, pPhysicalDevices); \
HookDefine2(VkResult, vkGetPhysicalDeviceFeatures, VkPhysicalDevice, physicalDevice, VkPhysicalDeviceFeatures*, pFeatures); \
HookDefine3(VkResult, vkGetPhysicalDeviceFormatProperties, VkPhysicalDevice, physicalDevice, VkFormat, format, VkFormatProperties*, pFormatProperties); \
+1 -1
View File
@@ -112,7 +112,7 @@ class VulkanResourceManager : public ResourceManager<WrappedVkRes*, TypedRealHan
ResourceId id = ResourceIDGen::GetNewUniqueID();
typename UnwrapHelper<realtype>::Outer *wrapped = new typename UnwrapHelper<realtype>::Outer(obj, id);
SetTableIfDispatchable(m_State >= WRITING, parentObj, wrapped);
SetTableIfDispatchable(m_State >= WRITING, parentObj, m_Core, wrapped);
AddCurrentResource(id, wrapped);
+29 -19
View File
@@ -128,34 +128,38 @@ struct WrappedVkNonDispRes : public WrappedVkRes
VkResourceRecord *record;
};
class WrappedVulkan;
struct WrappedVkDispRes : public WrappedVkRes
{
WrappedVkDispRes(VkInstance obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL)
WrappedVkDispRes(VkInstance obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL), core(NULL)
{ loaderTable = *(uintptr_t*)obj; }
WrappedVkDispRes(VkPhysicalDevice obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL)
WrappedVkDispRes(VkPhysicalDevice obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL), core(NULL)
{ loaderTable = *(uintptr_t*)obj; }
WrappedVkDispRes(VkDevice obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL)
WrappedVkDispRes(VkDevice obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL), core(NULL)
{ loaderTable = *(uintptr_t*)obj; }
WrappedVkDispRes(VkQueue obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL)
WrappedVkDispRes(VkQueue obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL), core(NULL)
{ loaderTable = *(uintptr_t*)obj; }
WrappedVkDispRes(VkCmdBuffer obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL)
WrappedVkDispRes(VkCmdBuffer obj, ResourceId objId) : table(0), real((void *)obj), id(objId), record(NULL), core(NULL)
{ loaderTable = *(uintptr_t*)obj; }
// VKTODOLOW there's padding here on 32-bit but I don't know if I really care about 32-bit.
// preserve dispatch table pointer in dispatchable objects
uintptr_t loaderTable, table;
RealVkRes real;
ResourceId id;
VkResourceRecord *record;
// we store this here so that any entry point with a dispatchable object can find the
// write instance to invoke into, without needing to keep any around. Its lifetime is
// tied to the VkInstance
WrappedVulkan *core;
};
// ensure the structs don't accidentally get made larger
RDCCOMPILE_ASSERT(sizeof(WrappedVkDispRes) == (sizeof(uint64_t)*3 + sizeof(uintptr_t)*2), "Wrapped resource struct has changed size! This is bad");
RDCCOMPILE_ASSERT(sizeof(WrappedVkDispRes) == (sizeof(uint64_t)*2 + sizeof(uintptr_t)*4), "Wrapped resource struct has changed size! This is bad");
RDCCOMPILE_ASSERT(sizeof(WrappedVkNonDispRes) == sizeof(uint64_t)*3, "Wrapped resource struct has changed size! This is bad");
// VKTODOLOW check that the pool counts approximated below are good for typical applications
@@ -449,6 +453,12 @@ typename UnwrapHelper<RealType>::Outer::DispatchTableType *ObjDisp(RealType obj)
return (typename UnwrapHelper<RealType>::Outer::DispatchTableType *)GetWrapped(obj)->table;
}
template<typename RealType>
WrappedVulkan *CoreDisp(RealType obj)
{
return (WrappedVulkan *)GetWrapped(obj)->core;
}
template<typename RealType>
RealType Unwrap(RealType obj)
{
@@ -500,17 +510,17 @@ TypedRealHandle ToTypedHandle(RealType obj)
}
template<typename parenttype, typename wrappedtype>
inline void SetTableIfDispatchable(bool writing, parenttype parent, wrappedtype *obj) {}
template<> inline void SetTableIfDispatchable(bool writing, VkInstance parent, WrappedVkInstance *obj)
{ SetDispatchTable(writing, parent, obj); }
template<> inline void SetTableIfDispatchable(bool writing, VkInstance parent, WrappedVkPhysicalDevice *obj)
{ SetDispatchTable(writing, parent, obj); }
template<> inline void SetTableIfDispatchable(bool writing, VkDevice parent, WrappedVkDevice *obj)
{ SetDispatchTable(writing, parent, obj); }
template<> inline void SetTableIfDispatchable(bool writing, VkDevice parent, WrappedVkQueue *obj)
{ SetDispatchTable(writing, parent, obj); }
template<> inline void SetTableIfDispatchable(bool writing, VkDevice parent, WrappedVkCmdBuffer *obj)
{ SetDispatchTable(writing, parent, obj); }
inline void SetTableIfDispatchable(bool writing, parenttype parent, WrappedVulkan *core, wrappedtype *obj) {}
template<> inline void SetTableIfDispatchable(bool writing, VkInstance parent, WrappedVulkan *core, WrappedVkInstance *obj)
{ SetDispatchTable(writing, parent, core, obj); }
template<> inline void SetTableIfDispatchable(bool writing, VkInstance parent, WrappedVulkan *core, WrappedVkPhysicalDevice *obj)
{ SetDispatchTable(writing, parent, core, obj); }
template<> inline void SetTableIfDispatchable(bool writing, VkDevice parent, WrappedVulkan *core, WrappedVkDevice *obj)
{ SetDispatchTable(writing, parent, core, obj); }
template<> inline void SetTableIfDispatchable(bool writing, VkDevice parent, WrappedVulkan *core, WrappedVkQueue *obj)
{ SetDispatchTable(writing, parent, core, obj); }
template<> inline void SetTableIfDispatchable(bool writing, VkDevice parent, WrappedVulkan *core, WrappedVkCmdBuffer *obj)
{ SetDispatchTable(writing, parent, core, obj); }
bool IsDispatchableRes(WrappedVkRes *ptr);
VkResourceType IdentifyTypeByPtr(WrappedVkRes *ptr);
+27 -19
View File
@@ -30,6 +30,7 @@
#include "vk_common.h"
#include "vk_core.h"
#include "vk_resources.h"
#include "vk_hookset_defs.h"
#include "common/common.h"
@@ -48,40 +49,52 @@ void InitInstanceTable(const VkBaseLayerObject *obj);
// RenderDoc State
WrappedVulkan *shadowVulkan = NULL;
// RenderDoc Intercepts, these must all be entry points with a dispatchable object
// as the first parameter
// RenderDoc Intercepts
#define HookDefine0(ret, function) \
ret VKAPI CONCAT(hooked_, function)() \
{ return shadowVulkan->function(); }
#define HookDefine1(ret, function, t1, p1) \
ret VKAPI CONCAT(hooked_, function)(t1 p1) \
{ return shadowVulkan->function(p1); }
{ return CoreDisp(p1)->function(p1); }
#define HookDefine2(ret, function, t1, p1, t2, p2) \
ret VKAPI CONCAT(hooked_, function)(t1 p1, t2 p2) \
{ return shadowVulkan->function(p1, p2); }
{ return CoreDisp(p1)->function(p1, p2); }
#define HookDefine3(ret, function, t1, p1, t2, p2, t3, p3) \
ret VKAPI CONCAT(hooked_, function)(t1 p1, t2 p2, t3 p3) \
{ return shadowVulkan->function(p1, p2, p3); }
{ return CoreDisp(p1)->function(p1, p2, p3); }
#define HookDefine4(ret, function, t1, p1, t2, p2, t3, p3, t4, p4) \
ret VKAPI CONCAT(hooked_, function)(t1 p1, t2 p2, t3 p3, t4 p4) \
{ return shadowVulkan->function(p1, p2, p3, p4); }
{ return CoreDisp(p1)->function(p1, p2, p3, p4); }
#define HookDefine5(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5) \
ret VKAPI CONCAT(hooked_, function)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) \
{ return shadowVulkan->function(p1, p2, p3, p4, p5); }
{ return CoreDisp(p1)->function(p1, p2, p3, p4, p5); }
#define HookDefine6(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6) \
ret VKAPI CONCAT(hooked_, function)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) \
{ return shadowVulkan->function(p1, p2, p3, p4, p5, p6); }
{ return CoreDisp(p1)->function(p1, p2, p3, p4, p5, p6); }
#define HookDefine7(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7) \
ret VKAPI CONCAT(hooked_, function)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) \
{ return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7); }
{ return CoreDisp(p1)->function(p1, p2, p3, p4, p5, p6, p7); }
#define HookDefine8(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8) \
ret VKAPI CONCAT(hooked_, function)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8) \
{ return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8); }
{ return CoreDisp(p1)->function(p1, p2, p3, p4, p5, p6, p7, p8); }
DefineHooks();
// need to implement vkCreateInstance and vkDestroyInstance specially,
// to create and destroy the core WrappedVulkan object
VkResult hooked_vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance)
{
WrappedVulkan *core = new WrappedVulkan("");
return core->vkCreateInstance(pCreateInfo, pInstance);
}
void hooked_vkDestroyInstance(VkInstance instance)
{
WrappedVulkan *core = CoreDisp(instance);
core->vkDestroyInstance(instance);
delete core;
}
// Layer Intercepts
static const VkLayerProperties physLayers[] = {
@@ -184,11 +197,6 @@ VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI RenderDoc_GetInstanceProcAddr(VkInstanc
/* loader uses this to force layer initialization; instance object is wrapped */
if (!strcmp("vkGetInstanceProcAddr", pName)) {
InitInstanceTable((const VkBaseLayerObject *) instance);
// VKTODOLOW I think this will be created and passed down in wrapped dispatchable
// objects
if (shadowVulkan == NULL) {
shadowVulkan = new WrappedVulkan("");
}
return (PFN_vkVoidFunction) &RenderDoc_GetInstanceProcAddr;
}