Implemented playback of current format.

This commit is contained in:
Adam Sawicki 2018-08-07 16:20:34 +02:00
parent 9d7d848658
commit ec5fecf51a

View File

@ -22,6 +22,7 @@
#include "VmaUsage.h"
#include "Common.h"
#include <unordered_map>
static const int RESULT_EXCEPTION = -1000;
static const int RESULT_ERROR_COMMAND_LINE = -1;
@ -36,6 +37,35 @@ struct StrRange
size_t length() const { return end - beg; }
};
static inline bool StrRangeEq(const StrRange& lhs, const char* rhsSz)
{
const size_t rhsLen = strlen(rhsSz);
return rhsLen == lhs.length() &&
memcmp(lhs.beg, rhsSz, rhsLen) == 0;
}
static inline bool StrRangeToUint(const StrRange& s, uint32_t& out)
{
// TODO handle failure.
char* end = (char*)s.end;
out = (uint32_t)strtoul(s.beg, &end, 10);
return true;
}
static inline bool StrRangeToUint(const StrRange& s, uint64_t& out)
{
// TODO handle failure.
char* end = (char*)s.end;
out = (uint64_t)strtoull(s.beg, &end, 10);
return true;
}
static inline bool StrRangeToPtr(const StrRange& s, uint64_t& out)
{
// TODO handle failure.
char* end = (char*)s.end;
out = (uint64_t)strtoull(s.beg, &end, 16);
return true;
}
////////////////////////////////////////////////////////////////////////////////
// LineSplit class
@ -89,10 +119,11 @@ public:
void Set(const StrRange& line, size_t maxCount = RANGE_COUNT_MAX);
size_t GetCount() const { return m_Count; }
void GetRange(size_t index, const char*& outBeg, const char*& outEnd) const
StrRange GetRange(size_t index) const
{
outBeg = m_Str + m_Ranges[index * 2];
outEnd = m_Str + m_Ranges[index * 2 + 1];
return StrRange {
m_Str + m_Ranges[index * 2],
m_Str + m_Ranges[index * 2 + 1] };
}
private:
@ -175,6 +206,8 @@ static bool IsLayerSupported(const VkLayerProperties* pProps, size_t propCount,
}) != propsEnd;
}
static const size_t FIRST_PARAM_INDEX = 4;
class Player
{
public:
@ -185,10 +218,7 @@ public:
void ExecuteLine(size_t lineNumber, const StrRange& line);
private:
static const size_t MAX_WARNINGS_TO_SHOW = 16;
// Increments warning counter. Returns true if warning message should be printed.
bool IssueWarning() { return m_WarningCount++ < MAX_WARNINGS_TO_SHOW; }
static const size_t MAX_WARNINGS_TO_SHOW = 64;
size_t m_WarningCount = 0;
@ -203,9 +233,44 @@ private:
PFN_vkDestroyDebugReportCallbackEXT m_pvkDestroyDebugReportCallbackEXT;
VkDebugReportCallbackEXT m_hCallback;
uint32_t m_VmaFrameIndex = 0;
// Any of these handles null means it was created in original but couldn't be created now.
struct Pool
{
VmaPool pool;
};
struct Buffer
{
VkBuffer buffer;
VmaAllocation allocation;
};
struct Image
{
VkImage image;
VmaAllocation allocation;
};
std::unordered_map<uint64_t, Pool> m_Pools;
std::unordered_map<uint64_t, Buffer> m_Buffers;
std::unordered_map<uint64_t, Image> m_Images;
// Increments warning counter. Returns true if warning message should be printed.
bool IssueWarning() { return m_WarningCount++ < MAX_WARNINGS_TO_SHOW; }
void InitVulkan();
void FinalizeVulkan();
void RegisterDebugCallbacks();
// If parmeter count doesn't match, issues warning and returns false.
bool ValidateFunctionParameterCount(size_t lineNumber, const CsvSplit& csvSplit, size_t expectedParamCount, bool lastUnbound);
void CreatePool(size_t lineNumber, const CsvSplit& csvSplit);
void DestroyPool(size_t lineNumber, const CsvSplit& csvSplit);
void CreateBuffer(size_t lineNumber, const CsvSplit& csvSplit);
void DestroyBuffer(size_t lineNumber, const CsvSplit& csvSplit);
void CreateImage(size_t lineNumber, const CsvSplit& csvSplit);
void DestroyImage(size_t lineNumber, const CsvSplit& csvSplit);
};
Player::Player()
@ -221,7 +286,7 @@ Player::~Player()
{
FinalizeVulkan();
if(m_WarningCount > 0)
if(m_WarningCount > MAX_WARNINGS_TO_SHOW)
printf("WARNING: %zu more warnings not shown.\n", m_WarningCount - MAX_WARNINGS_TO_SHOW);
}
@ -230,9 +295,58 @@ void Player::ExecuteLine(size_t lineNumber, const StrRange& line)
CsvSplit csvSplit;
csvSplit.Set(line);
if(csvSplit.GetCount() >= 4)
if(csvSplit.GetCount() >= FIRST_PARAM_INDEX)
{
// TODO
// Update VMA current frame index.
StrRange frameIndexStr = csvSplit.GetRange(2);
uint32_t frameIndex;
if(StrRangeToUint(frameIndexStr, frameIndex))
{
if(frameIndex != m_VmaFrameIndex)
{
vmaSetCurrentFrameIndex(m_Allocator, frameIndex);
m_VmaFrameIndex = frameIndex;
}
}
else
{
if(IssueWarning())
printf("Line %zu: Incorrect frame index.\n", lineNumber);
}
StrRange functionName = csvSplit.GetRange(3);
if(StrRangeEq(functionName, "vmaCreateAllocator"))
{
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 0, false))
{
// Nothing to do.
}
}
else if(StrRangeEq(functionName, "vmaCreatePool"))
CreatePool(lineNumber, csvSplit);
else if(StrRangeEq(functionName, "vmaDestroyPool"))
DestroyPool(lineNumber, csvSplit);
else if(StrRangeEq(functionName, "vmaSetAllocationUserData"))
{
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 2, true))
{
// Ignore for now.
}
}
else if(StrRangeEq(functionName, "vmaCreateBuffer"))
CreateBuffer(lineNumber, csvSplit);
else if(StrRangeEq(functionName, "vmaDestroyBuffer"))
DestroyBuffer(lineNumber, csvSplit);
else if(StrRangeEq(functionName, "vmaCreateImage"))
CreateImage(lineNumber, csvSplit);
else if(StrRangeEq(functionName, "vmaDestroyImage"))
DestroyImage(lineNumber, csvSplit);
else
{
if(IssueWarning())
printf("Line %zu: Unknown function.\n", lineNumber);
}
}
else
{
@ -289,6 +403,8 @@ void Player::InitVulkan()
ERR_GUARD_VULKAN( vkCreateInstance(&instInfo, NULL, &m_VulkanInstance) );
RegisterDebugCallbacks();
// Find physical device
uint32_t deviceCount = 0;
@ -340,7 +456,7 @@ void Player::InitVulkan()
// Determine list of device extensions to enable.
std::vector<const char*> enabledDeviceExtensions;
enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
//enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
{
uint32_t propertyCount = 0;
ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(m_PhysicalDevice, nullptr, &propertyCount, nullptr) );
@ -391,6 +507,36 @@ void Player::InitVulkan()
void Player::FinalizeVulkan()
{
if(!m_Images.empty())
{
printf("WARNING: Images not destroyed: %zu.\n", m_Images.size());
for(const auto it : m_Images)
{
vmaDestroyImage(m_Allocator, it.second.image, it.second.allocation);
}
}
if(!m_Buffers.empty())
{
printf("WARNING: Buffers not destroyed: %zu.\n", m_Buffers.size());
for(const auto it : m_Buffers)
{
vmaDestroyBuffer(m_Allocator, it.second.buffer, it.second.allocation);
}
}
if(!m_Pools.empty())
{
printf("WARNING: Pools not destroyed: %zu.\n", m_Pools.size());
for(const auto it : m_Pools)
{
vmaDestroyPool(m_Allocator, it.second.pool);
}
}
vkDeviceWaitIdle(m_Device);
if(m_Allocator != VK_NULL_HANDLE)
@ -433,20 +579,287 @@ void Player::RegisterDebugCallbacks()
assert(m_pvkDebugReportMessageEXT);
assert(m_pvkDestroyDebugReportCallbackEXT);
VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
callbackCreateInfo.pNext = nullptr;
VkDebugReportCallbackCreateInfoEXT callbackCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
callbackCreateInfo.flags = //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
VK_DEBUG_REPORT_ERROR_BIT_EXT |
VK_DEBUG_REPORT_WARNING_BIT_EXT |
VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT /*|
VK_DEBUG_REPORT_DEBUG_BIT_EXT*/;
callbackCreateInfo.pfnCallback = &MyDebugReportCallback;
callbackCreateInfo.pUserData = nullptr;
ERR_GUARD_VULKAN( m_pvkCreateDebugReportCallbackEXT(m_VulkanInstance, &callbackCreateInfo, nullptr, &m_hCallback) );
}
bool Player::ValidateFunctionParameterCount(size_t lineNumber, const CsvSplit& csvSplit, size_t expectedParamCount, bool lastUnbound)
{
bool ok;
if(lastUnbound)
ok = csvSplit.GetCount() >= FIRST_PARAM_INDEX + expectedParamCount - 1;
else
ok = csvSplit.GetCount() == FIRST_PARAM_INDEX + expectedParamCount;
if(!ok)
{
if(IssueWarning())
printf("Line %zu: Incorrect number of function parameters.\n", lineNumber);
}
return ok;
}
void Player::CreatePool(size_t lineNumber, const CsvSplit& csvSplit)
{
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 7, false))
{
VmaPoolCreateInfo poolCreateInfo = {};
uint64_t origPtr = 0;
if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), poolCreateInfo.memoryTypeIndex) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), poolCreateInfo.flags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), poolCreateInfo.blockSize) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), poolCreateInfo.minBlockCount) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), poolCreateInfo.maxBlockCount) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), poolCreateInfo.frameInUseCount) &&
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), origPtr))
{
Pool poolDesc = {};
VkResult res = vmaCreatePool(m_Allocator, &poolCreateInfo, &poolDesc.pool);
if(res == VK_SUCCESS)
{
const auto existingIt = m_Pools.find(origPtr);
if(existingIt != m_Pools.end())
{
if(IssueWarning())
printf("Line %zu: Pool %llX already exists.\n", lineNumber, origPtr);
}
}
else
{
if(IssueWarning())
printf("Line %zu: vmaCreatePool failed (%u).\n", lineNumber, res);
}
m_Pools[origPtr] = poolDesc;
}
else
{
if(IssueWarning())
printf("Line %zu: Invalid parameters for vmaCreatePool.\n", lineNumber);
}
}
}
void Player::DestroyPool(size_t lineNumber, const CsvSplit& csvSplit)
{
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
{
uint64_t origPtr = 0;
if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
{
const auto it = m_Pools.find(origPtr);
if(it != m_Pools.end())
{
vmaDestroyPool(m_Allocator, it->second.pool);
m_Pools.erase(it);
}
else
{
if(IssueWarning())
printf("Line %zu: Pool %llX not found.\n", lineNumber, origPtr);
}
}
else
{
if(IssueWarning())
printf("Line %zu: Invalid parameters for vmaDestroyPool.\n", lineNumber);
}
}
}
void Player::CreateBuffer(size_t lineNumber, const CsvSplit& csvSplit)
{
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 12, true))
{
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
VmaAllocationCreateInfo allocCreateInfo = {};
uint64_t origPool = 0;
uint64_t origPtr = 0;
if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), bufCreateInfo.flags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), bufCreateInfo.size) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), bufCreateInfo.usage) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), (uint32_t&)bufCreateInfo.sharingMode) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), allocCreateInfo.flags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), (uint32_t&)allocCreateInfo.usage) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), allocCreateInfo.requiredFlags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), allocCreateInfo.preferredFlags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), allocCreateInfo.memoryTypeBits) &&
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 9), origPool) &&
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 10), origPtr))
{
if(origPool != 0)
{
const auto poolIt = m_Pools.find(origPool);
if(poolIt != m_Pools.end())
allocCreateInfo.pool = poolIt->second.pool;
else
{
if(IssueWarning())
printf("Line %zu: Pool %llX not found.\n", lineNumber, origPool);
}
}
Buffer bufDesc = {};
VkResult res = vmaCreateBuffer(m_Allocator, &bufCreateInfo, &allocCreateInfo, &bufDesc.buffer, &bufDesc.allocation, nullptr);
if(res == VK_SUCCESS)
{
const auto existingIt = m_Buffers.find(origPtr);
if(existingIt != m_Buffers.end())
{
if(IssueWarning())
printf("Line %zu: Allocation %llX for buffer already exists.\n", lineNumber, origPtr);
}
}
else
{
if(IssueWarning())
printf("Line %zu: vmaCreateBuffer failed (%u).\n", lineNumber, res);
}
m_Buffers[origPtr] = bufDesc;
}
else
{
if(IssueWarning())
printf("Line %zu: Invalid parameters for vmaCreateBuffer.\n", lineNumber);
}
}
}
void Player::DestroyBuffer(size_t lineNumber, const CsvSplit& csvSplit)
{
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
{
uint64_t origAllocPtr = 0;
if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origAllocPtr))
{
const auto it = m_Buffers.find(origAllocPtr);
if(it != m_Buffers.end())
{
vmaDestroyBuffer(m_Allocator, it->second.buffer, it->second.allocation);
m_Buffers.erase(it);
}
else
{
if(IssueWarning())
printf("Line %zu: Allocation %llX for buffer not found.\n", lineNumber, origAllocPtr);
}
}
else
{
if(IssueWarning())
printf("Line %zu: Invalid parameters for vmaDestroyBuffer.\n", lineNumber);
}
}
}
void Player::CreateImage(size_t lineNumber, const CsvSplit& csvSplit)
{
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 21, true))
{
VkImageCreateInfo imageCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
VmaAllocationCreateInfo allocCreateInfo = {};
uint64_t origPool = 0;
uint64_t origPtr = 0;
if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), imageCreateInfo.flags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), (uint32_t&)imageCreateInfo.imageType) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), (uint32_t&)imageCreateInfo.format) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), imageCreateInfo.extent.width) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), imageCreateInfo.extent.height) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), imageCreateInfo.extent.depth) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), imageCreateInfo.mipLevels) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), imageCreateInfo.arrayLayers) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), (uint32_t&)imageCreateInfo.samples) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 9), (uint32_t&)imageCreateInfo.tiling) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 10), imageCreateInfo.usage) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 11), (uint32_t&)imageCreateInfo.sharingMode) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 12), (uint32_t&)imageCreateInfo.initialLayout) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 13), allocCreateInfo.flags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 14), (uint32_t&)allocCreateInfo.usage) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 15), allocCreateInfo.requiredFlags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 16), allocCreateInfo.preferredFlags) &&
StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 17), allocCreateInfo.memoryTypeBits) &&
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 18), origPool) &&
StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 19), origPtr))
{
if(origPool != 0)
{
const auto poolIt = m_Pools.find(origPool);
if(poolIt != m_Pools.end())
allocCreateInfo.pool = poolIt->second.pool;
else
{
if(IssueWarning())
printf("Line %zu: Pool %llX not found.\n", lineNumber, origPool);
}
}
Image imageDesc = {};
VkResult res = vmaCreateImage(m_Allocator, &imageCreateInfo, &allocCreateInfo, &imageDesc.image, &imageDesc.allocation, nullptr);
if(res == VK_SUCCESS)
{
const auto existingIt = m_Images.find(origPtr);
if(existingIt != m_Images.end())
{
if(IssueWarning())
printf("Line %zu: Allocation %llX for image already exists.\n", lineNumber, origPtr);
}
}
else
{
if(IssueWarning())
printf("Line %zu: vmaCreateImage failed (%u).\n", lineNumber, res);
}
m_Images[origPtr] = imageDesc;
}
else
{
if(IssueWarning())
printf("Line %zu: Invalid parameters for vmaCreateImage.\n", lineNumber);
}
}
}
void Player::DestroyImage(size_t lineNumber, const CsvSplit& csvSplit)
{
if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
{
uint64_t origAllocPtr = 0;
if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origAllocPtr))
{
const auto it = m_Images.find(origAllocPtr);
if(it != m_Images.end())
{
vmaDestroyImage(m_Allocator, it->second.image, it->second.allocation);
m_Images.erase(it);
}
else
{
if(IssueWarning())
printf("Line %zu: Allocation %llX for image not found.\n", lineNumber, origAllocPtr);
}
}
else
{
if(IssueWarning())
printf("Line %zu: Invalid parameters for vmaDestroyBuffer.\n", lineNumber);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Main functions
@ -456,13 +869,6 @@ static void PrintCommandLineSyntax()
" VmaReplay <SrcFile.csv>\n");
}
static inline bool StrRangeEq(const StrRange& lhs, const char* rhsSz)
{
const size_t rhsLen = strlen(rhsSz);
return rhsLen == lhs.length() &&
memcmp(lhs.beg, rhsSz, rhsLen) == 0;
}
static int ProcessFile(const char* data, size_t numBytes)
{
// Begin stats.
@ -488,12 +894,14 @@ static int ProcessFile(const char* data, size_t numBytes)
Player player;
player.Init();
printf("Playing...\n");
while(lineSplit.GetNextLine(line))
{
player.ExecuteLine(lineSplit.GetNextLineIndex(), line);
}
// End stats.
printf("Done.\n");
printf("File lines: %zu\n", lineSplit.GetNextLineIndex());
return 0;
@ -532,8 +940,6 @@ static int ProcessFile(const char* filePath)
result = RESULT_ERROR_SOURCE_FILE;
}
printf("Done.\n");
return result;
}