Initial commit (should probably have done this earlier).
This commit is contained in:
39
source/common.hpp
Normal file
39
source/common.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(VK_CAPTURE_COMMON_HPP_INCLUDED)
|
||||
#define VK_CAPTURE_COMMON_HPP_INCLUDED 1
|
||||
|
||||
#include <cstddef>
|
||||
#include "vk_capture.h"
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
VkVariantMWN* allocVariant(std::size_t num);
|
||||
void* allocData(std::size_t bytes, std::size_t alignment = 1);
|
||||
|
||||
template<typename T>
|
||||
inline T* allocType(std::size_t count = 1) {
|
||||
return static_cast<T*>(allocData(sizeof(T) * count, alignof(T)));
|
||||
}
|
||||
|
||||
} // namespace vk_capture
|
||||
|
||||
#endif // !defined(VK_CAPTURE_COMMON_HPP_INCLUDED)
|
||||
57
source/data_pool.cpp
Normal file
57
source/data_pool.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
#include "data_pool.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// internal defines
|
||||
//
|
||||
|
||||
//
|
||||
// internal constants
|
||||
//
|
||||
|
||||
//
|
||||
// internal types
|
||||
//
|
||||
|
||||
//
|
||||
// internal variables
|
||||
//
|
||||
|
||||
//
|
||||
// internal functions
|
||||
//
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
void* DataPool::allocate(std::size_t bytes, std::size_t alignment)
|
||||
{
|
||||
assert(bytes > 0 && bytes <= PAGE_SIZE);
|
||||
assert(alignment > 0 && alignment <= alignof(std::max_align_t));
|
||||
|
||||
if (offset % alignment != 0) {
|
||||
offset += alignment - (offset % alignment);
|
||||
}
|
||||
|
||||
const std::size_t remainingOnPage = PAGE_SIZE - (offset % PAGE_SIZE);
|
||||
if (remainingOnPage == PAGE_SIZE || remainingOnPage < bytes)
|
||||
{
|
||||
// next page
|
||||
pages.push_back(std::make_unique<Page>());
|
||||
offset = PAGE_SIZE * (pages.size() - 1);
|
||||
}
|
||||
const std::size_t page = offset / PAGE_SIZE;
|
||||
const std::size_t localOffset = offset % PAGE_SIZE;
|
||||
std::uint8_t* result = &(*pages[page])[localOffset];
|
||||
offset += bytes;
|
||||
assert(reinterpret_cast<std::uintptr_t>(result) % alignment == 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace vk_capture
|
||||
50
source/data_pool.hpp
Normal file
50
source/data_pool.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(VK_CAPTURE_DATA_POOL_HPP_INCLUDED)
|
||||
#define VK_CAPTURE_DATA_POOL_HPP_INCLUDED 1
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
struct DataPool
|
||||
{
|
||||
static constexpr std::size_t PAGE_SIZE = 4096 * 1024;
|
||||
static_assert(PAGE_SIZE % alignof(std::max_align_t) == 0);
|
||||
|
||||
struct alignas(std::max_align_t) Page : std::array<std::uint8_t, PAGE_SIZE> {};
|
||||
|
||||
using page_ptr_t = std::unique_ptr<Page>;
|
||||
|
||||
std::vector<page_ptr_t> pages;
|
||||
std::size_t offset = 0;
|
||||
|
||||
void* allocate(std::size_t bytes, std::size_t alignment = 1);
|
||||
inline void reset() { offset = 0; }
|
||||
};
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace vk_capture
|
||||
|
||||
#endif // !defined(VK_CAPTURE_DATA_POOL_HPP_INCLUDED)
|
||||
39
source/dispatch_table.cpp
Normal file
39
source/dispatch_table.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
#include "dispatch_table.hpp"
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// internal defines
|
||||
//
|
||||
|
||||
//
|
||||
// internal constants
|
||||
//
|
||||
|
||||
//
|
||||
// internal types
|
||||
//
|
||||
|
||||
//
|
||||
// internal variables
|
||||
//
|
||||
|
||||
//
|
||||
// internal functions
|
||||
//
|
||||
|
||||
//
|
||||
// public variables
|
||||
//
|
||||
|
||||
// TODO: this won't work for multi-device setups, we'd need a hashmap of sort then
|
||||
VkLayerInstanceDispatchTable g_instanceDispatchTable;
|
||||
VkLayerDispatchTable g_dispatchTable;
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace sekiei
|
||||
38
source/dispatch_table.hpp
Normal file
38
source/dispatch_table.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(VK_CAPTURE_DISPATCH_TABLE_HPP_INCLUDED)
|
||||
#define VK_CAPTURE_DISPATCH_TABLE_HPP_INCLUDED 1
|
||||
|
||||
#include <vulkan/vk_dispatch_table_helper.h>
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
//
|
||||
// public variables
|
||||
//
|
||||
|
||||
// TODO: this won't work for multi-device setups, we'd need a hashmap of sort then
|
||||
extern VkLayerInstanceDispatchTable g_instanceDispatchTable;
|
||||
extern VkLayerDispatchTable g_dispatchTable;
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace vk_capture
|
||||
|
||||
#endif // !defined(VK_CAPTURE_DISPATCH_TABLE_HPP_INCLUDED)
|
||||
3518
source/functions.cpp
Normal file
3518
source/functions.cpp
Normal file
File diff suppressed because it is too large
Load Diff
14
source/functions.hpp
Normal file
14
source/functions.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(VK_CAPTURE_FUNCTIONS_HPP_INCLUDED)
|
||||
#define VK_CAPTURE_FUNCTIONS_HPP_INCLUDED 1
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
PFN_vkVoidFunction getWrappedFunctionPtr(const char* pName);
|
||||
} // namespace vk_capture
|
||||
|
||||
#endif // VK_CAPTURE_FUNCTIONS_HPP_INCLUDED
|
||||
164
source/layer.cpp
Normal file
164
source/layer.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <vulkan/vk_layer.h>
|
||||
#include "dispatch_table.hpp"
|
||||
#include "functions.hpp"
|
||||
#include "record_list.hpp"
|
||||
#include "vk_capture.h"
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
inline constexpr std::uint32_t LOADER_LAYER_VERSION = 2;
|
||||
|
||||
PFN_vkVoidFunction getLayerFunctionPtr(const char* pName);
|
||||
|
||||
VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
|
||||
{
|
||||
const VkLayerInstanceCreateInfo* layerCreateInfo = static_cast<const VkLayerInstanceCreateInfo*>(pCreateInfo->pNext);
|
||||
|
||||
// step through the chain of pNext until we get to the link info
|
||||
while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
|
||||
layerCreateInfo->function != VK_LAYER_LINK_INFO))
|
||||
{
|
||||
layerCreateInfo = static_cast<const VkLayerInstanceCreateInfo*>(layerCreateInfo->pNext);
|
||||
}
|
||||
|
||||
if(layerCreateInfo == nullptr)
|
||||
{
|
||||
// No loader instance create info
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
PFN_vkGetInstanceProcAddr gpa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr;
|
||||
// move chain on for next layer
|
||||
const_cast<VkLayerInstanceCreateInfo*>(layerCreateInfo)->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext;
|
||||
|
||||
PFN_vkCreateInstance createFunc = reinterpret_cast<PFN_vkCreateInstance>(gpa(VK_NULL_HANDLE, "vkCreateInstance"));
|
||||
|
||||
VkResult ret = createFunc(pCreateInfo, pAllocator, pInstance);
|
||||
if (ret != VK_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
// fetch our own dispatch table for the functions we need, into the next layer
|
||||
layer_init_instance_dispatch_table(*pInstance, &vk_capture::g_instanceDispatchTable, gpa);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult vkCreateDevice(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkDeviceCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDevice* pDevice)
|
||||
{
|
||||
const VkLayerDeviceCreateInfo* layerCreateInfo = static_cast<const VkLayerDeviceCreateInfo*>(pCreateInfo->pNext);
|
||||
|
||||
// step through the chain of pNext until we get to the link info
|
||||
while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO ||
|
||||
layerCreateInfo->function != VK_LAYER_LINK_INFO))
|
||||
{
|
||||
layerCreateInfo = static_cast<const VkLayerDeviceCreateInfo*>(layerCreateInfo->pNext);
|
||||
}
|
||||
|
||||
if(layerCreateInfo == nullptr)
|
||||
{
|
||||
// No loader instance create info
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
PFN_vkGetInstanceProcAddr gipa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr;
|
||||
PFN_vkGetDeviceProcAddr gdpa = layerCreateInfo->u.pLayerInfo->pfnNextGetDeviceProcAddr;
|
||||
// move chain on for next layer
|
||||
const_cast<VkLayerDeviceCreateInfo*>(layerCreateInfo)->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext;
|
||||
|
||||
PFN_vkCreateDevice createFunc = (PFN_vkCreateDevice)gipa(VK_NULL_HANDLE, "vkCreateDevice");
|
||||
|
||||
VkResult ret = createFunc(physicalDevice, pCreateInfo, pAllocator, pDevice);
|
||||
|
||||
if (ret != VK_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
layer_init_device_dispatch_table(*pDevice, &vk_capture::g_dispatchTable, gdpa);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice device, const char* pName)
|
||||
{
|
||||
PFN_vkVoidFunction ptr = getLayerFunctionPtr(pName);
|
||||
if (ptr) {
|
||||
return ptr;
|
||||
}
|
||||
else {
|
||||
return g_dispatchTable.GetDeviceProcAddr(device, pName);
|
||||
}
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* pName)
|
||||
{
|
||||
PFN_vkVoidFunction ptr = getLayerFunctionPtr(pName);
|
||||
if (ptr) {
|
||||
return ptr;
|
||||
}
|
||||
else {
|
||||
return g_instanceDispatchTable.GetInstanceProcAddr(instance, pName);
|
||||
}
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction getLayerFunctionPtr(const char* pName)
|
||||
{
|
||||
if (std::strcmp(pName, "vkCreateInstance") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vk_capture::vkCreateInstance);
|
||||
}
|
||||
else if (std::strcmp(pName, "vkCreateDevice") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vk_capture::vkCreateDevice);
|
||||
}
|
||||
else if (std::strcmp(pName, "vkGetInstanceProcAddr") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vk_capture::vkGetInstanceProcAddr);
|
||||
}
|
||||
if (std::strcmp(pName, "vkGetDeviceProcAddr") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vkGetDeviceProcAddr);
|
||||
}
|
||||
else if (std::strcmp(pName, "vkAllocateRecordListMWN") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vkAllocateRecordListMWN);
|
||||
}
|
||||
else if (std::strcmp(pName, "vkFreeRecordListMWN") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vkFreeRecordListMWN);
|
||||
}
|
||||
else if (std::strcmp(pName, "vkBeginRecordingMWN") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vkBeginRecordingMWN);
|
||||
}
|
||||
else if (std::strcmp(pName, "vkEndRecordingMWN") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vkEndRecordingMWN);
|
||||
}
|
||||
else if (std::strcmp(pName, "vkGetRecordListItemsMWN") == 0) {
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(&vkGetRecordListItemsMWN);
|
||||
}
|
||||
else {
|
||||
return getWrappedFunctionPtr(pName);
|
||||
}
|
||||
}
|
||||
} // namespace vk_capture
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
VK_LAYER_EXPORT VkResult VKAPI_CALL vk_capture_vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface* pVersionStruct)
|
||||
{
|
||||
if (pVersionStruct->loaderLayerInterfaceVersion < vk_capture::LOADER_LAYER_VERSION) {
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
pVersionStruct->sType = LAYER_NEGOTIATE_INTERFACE_STRUCT;
|
||||
pVersionStruct->pNext = nullptr;
|
||||
pVersionStruct->loaderLayerInterfaceVersion = vk_capture::LOADER_LAYER_VERSION;
|
||||
pVersionStruct->pfnGetInstanceProcAddr = &vk_capture::vkGetInstanceProcAddr;
|
||||
pVersionStruct->pfnGetDeviceProcAddr = &vk_capture::vkGetDeviceProcAddr;
|
||||
pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
} // extern "C"
|
||||
94
source/record_list.cpp
Normal file
94
source/record_list.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
#include "record_list.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// internal defines
|
||||
//
|
||||
|
||||
//
|
||||
// internal constants
|
||||
//
|
||||
|
||||
//
|
||||
// internal types
|
||||
//
|
||||
|
||||
//
|
||||
// internal variables
|
||||
//
|
||||
|
||||
//
|
||||
// internal functions
|
||||
//
|
||||
|
||||
//
|
||||
// public variables
|
||||
//
|
||||
|
||||
VkRecordListMWN g_activeRecordList = nullptr; // TODO: per device and or per thread?
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
VkResult vkAllocateRecordListMWN(VkDevice /* device */, const VkRecordListAllocateInfoMWN* pAllocInfo, VkRecordListMWN* pRecordList)
|
||||
{
|
||||
(void) pAllocInfo;
|
||||
|
||||
VkRecordListMWN result = new VkRecordListMWN_T(); // TODO: use Vulkan allocators
|
||||
if (result == nullptr) {
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
*pRecordList = result;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void vkFreeRecordListMWN(VkDevice /* device */, VkRecordListMWN recordList)
|
||||
{
|
||||
assert(recordList != g_activeRecordList);
|
||||
delete recordList; // TODO: allocators
|
||||
}
|
||||
|
||||
VkResult vkBeginRecordingMWN(VkDevice /* device */, const VkRecordInfoMWN* pRecordInfo)
|
||||
{
|
||||
assert(g_activeRecordList == nullptr);
|
||||
assert(pRecordInfo && pRecordInfo->recordList);
|
||||
g_activeRecordList = pRecordInfo->recordList;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void vkEndRecordingMWN(VkDevice /* device */)
|
||||
{
|
||||
assert(g_activeRecordList != nullptr);
|
||||
g_activeRecordList = nullptr;
|
||||
}
|
||||
|
||||
VkResult vkGetRecordListItemsMWN(VkDevice /* device */, VkRecordListMWN recordList, uint32_t* pItemCount, VkRecordListItemMWN** pItems)
|
||||
{
|
||||
assert(pItemCount);
|
||||
assert(pItems);
|
||||
|
||||
*pItemCount = static_cast<std::uint32_t>(recordList->items.size());
|
||||
*pItems = recordList->items.data();
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkVariantMWN* allocVariant(std::size_t num)
|
||||
{
|
||||
assert(g_activeRecordList);
|
||||
return g_activeRecordList->values.allocate(num);
|
||||
}
|
||||
|
||||
void* allocData(std::size_t bytes, std::size_t alignment)
|
||||
{
|
||||
assert(g_activeRecordList);
|
||||
return g_activeRecordList->data.allocate(bytes, alignment);
|
||||
}
|
||||
|
||||
} // namespace vk_capture
|
||||
87
source/record_list.hpp
Normal file
87
source/record_list.hpp
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(VK_CAPTURE_RECORD_LIST_HPP_INCLUDED)
|
||||
#define VK_CAPTURE_RECORD_LIST_HPP_INCLUDED 1
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "data_pool.hpp"
|
||||
#include "variant_pool.hpp"
|
||||
#include "vk_capture.h"
|
||||
#include "vk_function_ids.h"
|
||||
|
||||
typedef struct VkRecordListMWN_T {
|
||||
std::vector<VkRecordListItemMWN> items; // TODO: use Vulkan allocators
|
||||
vk_capture::VariantPool values;
|
||||
vk_capture::DataPool data;
|
||||
} VkRecordListMWN_T;
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
//
|
||||
// public variables
|
||||
//
|
||||
|
||||
extern VkRecordListMWN g_activeRecordList;
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
VkResult vkAllocateRecordListMWN(VkDevice device, const VkRecordListAllocateInfoMWN* pAllocInfo, VkRecordListMWN* pRecordList);
|
||||
void vkFreeRecordListMWN(VkDevice device, VkRecordListMWN recordList);
|
||||
VkResult vkBeginRecordingMWN(VkDevice device, const VkRecordInfoMWN* pRecordInfo);
|
||||
void vkEndRecordingMWN(VkDevice device);
|
||||
VkResult vkGetRecordListItemsMWN(VkDevice device, VkRecordListMWN recordList, uint32_t* pItemCount, VkRecordListItemMWN** pItems);
|
||||
|
||||
template<typename TResult, typename... TArgs>
|
||||
void recordFunction(VkFunctionMWN function, const TResult& result, const TArgs&... args)
|
||||
{
|
||||
(void) result;
|
||||
if (!g_activeRecordList) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkRecordListItemMWN& item = g_activeRecordList->items.emplace_back();
|
||||
item.function = function;
|
||||
item.numParameters = static_cast<std::uint32_t>(sizeof...(TArgs));
|
||||
item.pParameterValues = g_activeRecordList->values.allocate(sizeof...(TArgs));
|
||||
variantWrap(result, item.returnValue);
|
||||
|
||||
VkVariantMWN* variant = item.pParameterValues;
|
||||
(variantWrap(args, *(variant++)), ...);
|
||||
}
|
||||
|
||||
template<typename... TArgs>
|
||||
void recordVoidFunction(VkFunctionMWN function, const TArgs&... args)
|
||||
{
|
||||
if (!g_activeRecordList) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkRecordListItemMWN& item = g_activeRecordList->items.emplace_back();
|
||||
item.function = function;
|
||||
item.numParameters = static_cast<std::uint32_t>(sizeof...(TArgs));
|
||||
item.pParameterValues = g_activeRecordList->values.allocate(sizeof...(TArgs));
|
||||
item.returnValue.type = VK_VARIANT_TYPE_NONE_MWN;
|
||||
|
||||
VkVariantMWN* variant = item.pParameterValues;
|
||||
(variantWrap(args, *(variant++)), ...);
|
||||
}
|
||||
} // namespace vk_capture
|
||||
|
||||
#endif // !defined(VK_CAPTURE_RECORD_LIST_HPP_INCLUDED)
|
||||
50
source/variant_pool.cpp
Normal file
50
source/variant_pool.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
#include "variant_pool.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// internal defines
|
||||
//
|
||||
|
||||
//
|
||||
// internal constants
|
||||
//
|
||||
|
||||
//
|
||||
// internal types
|
||||
//
|
||||
|
||||
//
|
||||
// internal variables
|
||||
//
|
||||
|
||||
//
|
||||
// internal functions
|
||||
//
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
VkVariantMWN* VariantPool::allocate(std::size_t num)
|
||||
{
|
||||
assert(num > 0 && num <= PAGE_SIZE);
|
||||
const std::size_t remainingOnPage = PAGE_SIZE - (nextIndex % PAGE_SIZE);
|
||||
if (remainingOnPage == PAGE_SIZE || remainingOnPage < num)
|
||||
{
|
||||
// next page
|
||||
pages.push_back(std::make_unique<page_t>());
|
||||
nextIndex = PAGE_SIZE * (pages.size() - 1);
|
||||
}
|
||||
const std::size_t page = nextIndex / PAGE_SIZE;
|
||||
const std::size_t localIndex = nextIndex % PAGE_SIZE;
|
||||
VkVariantMWN* result = &(*pages[page])[localIndex];
|
||||
nextIndex += num;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace v
|
||||
146
source/variant_pool.hpp
Normal file
146
source/variant_pool.hpp
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(VK_CAPTURE_VARIANT_POOL_HPP_INCLUDED)
|
||||
#define VK_CAPTURE_VARIANT_POOL_HPP_INCLUDED 1
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "common.hpp"
|
||||
#include "variant_wrap.hpp"
|
||||
#include "vk_capture.h"
|
||||
|
||||
namespace vk_capture
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
struct VariantPool
|
||||
{
|
||||
static constexpr std::size_t PAGE_SIZE = 1024;
|
||||
using page_t = std::array<VkVariantMWN, PAGE_SIZE>;
|
||||
using page_ptr_t = std::unique_ptr<page_t>;
|
||||
|
||||
std::vector<page_ptr_t> pages;
|
||||
std::size_t nextIndex = 0;
|
||||
|
||||
VkVariantMWN* allocate(std::size_t num = 1);
|
||||
inline void reset() { nextIndex = 0; }
|
||||
};
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
template<typename TValue>
|
||||
inline void variantWrap(const TValue& /* value */, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_UNKNOWN_MWN;
|
||||
}
|
||||
|
||||
inline void variantWrap(bool value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_BOOL_MWN;
|
||||
outVariant.uintValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(std::uint8_t value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_UINT8_MWN;
|
||||
outVariant.uintValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(std::int8_t value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_INT8_MWN;
|
||||
outVariant.intValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(std::uint16_t value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_UINT16_MWN;
|
||||
outVariant.uintValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(std::int16_t value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_INT16_MWN;
|
||||
outVariant.intValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(std::uint32_t value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_UINT32_MWN;
|
||||
outVariant.uintValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(std::int32_t value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_INT32_MWN;
|
||||
outVariant.intValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(std::uint64_t value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_UINT64_MWN;
|
||||
outVariant.uintValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(std::int64_t value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_INT64_MWN;
|
||||
outVariant.intValue = value;
|
||||
}
|
||||
|
||||
inline void variantWrap(const void* value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_VOID_POINTER_MWN;
|
||||
outVariant.voidPointerValue = value;
|
||||
}
|
||||
|
||||
template<typename TPointed>
|
||||
inline void variantWrap(const TPointed* value, VkVariantMWN& outVariant);
|
||||
|
||||
template<typename TEle, std::size_t count>
|
||||
inline void variantWrap(const TEle (&value)[count], VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_ARRAY_MWN;
|
||||
outVariant.arrayValue.numElements = count;
|
||||
outVariant.arrayValue.elements = allocVariant(count);
|
||||
|
||||
for (std::size_t idx = 0; idx < count; ++idx) {
|
||||
variantWrap(value[idx], outVariant.arrayValue.elements[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TPointed>
|
||||
inline void variantWrap(const TPointed* value, VkVariantMWN& outVariant)
|
||||
{
|
||||
outVariant.type = VK_VARIANT_TYPE_POINTER_MWN;
|
||||
if (value != nullptr)
|
||||
{
|
||||
outVariant.pointerValue = allocVariant(1);
|
||||
variantWrap(*value, *outVariant.pointerValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: now the type is missing ...
|
||||
outVariant.pointerValue = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vk_capture
|
||||
|
||||
#endif // !defined(VK_CAPTURE_VARIANT_POOL_HPP_INCLUDED)
|
||||
19673
source/variant_wrap.hpp
Normal file
19673
source/variant_wrap.hpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user