Added Pipeline Caching.

This commit is contained in:
Anish Bhobe 2024-07-27 15:19:39 +02:00
parent f9517db592
commit 22cbc41af1
6 changed files with 98 additions and 5 deletions

View File

@ -20,7 +20,7 @@ set(HEADER_FILES
physical_device.h physical_device.h
device.h device.h
swapchain.h swapchain.h
"pipeline.h" pipeline.h
queue_allocation.h queue_allocation.h
buffer.h) buffer.h)

View File

@ -19,6 +19,13 @@ constexpr eastl::array DEVICE_EXTENSIONS = {
Device::Device(const Context *context, PhysicalDevice *physicalDevice, Features *enabledFeatures, Device::Device(const Context *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
const eastl::vector<QueueAllocation> &queueAllocations, NameString &&name) const eastl::vector<QueueAllocation> &queueAllocations, NameString &&name)
: Device(context, physicalDevice, enabledFeatures, queueAllocations, {}, std::move(name))
{
}
Device::Device(const Context *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
const eastl::vector<QueueAllocation> &queueAllocations, eastl::span<u8> &&pipelineCacheData,
NameString &&name)
: m_Name(std::move(name)) : m_Name(std::move(name))
, m_PhysicalDevice(physicalDevice->m_PhysicalDevice) , m_PhysicalDevice(physicalDevice->m_PhysicalDevice)
{ {
@ -86,11 +93,22 @@ Device::Device(const Context *context, PhysicalDevice *physicalDevice, Features
THEN_ABORT(result) THEN_ABORT(result)
ELSE_VERBOSE("Memory Allocator Created"); ELSE_VERBOSE("Memory Allocator Created");
DEBUG("Created '{}' Successfully", m_Name); vk::PipelineCacheCreateInfo pipelineCacheCreateInfo = {
.initialDataSize = pipelineCacheData.size_bytes(),
.pInitialData = pipelineCacheData.data(),
};
result = m_Device.createPipelineCache(&pipelineCacheCreateInfo, nullptr, &m_PipelineCache);
ERROR_IF(Failed(result), "Pipeline Cache creation failed. Cause: {}", result)
DO(m_Device.destroy(nullptr))
THEN_ABORT(result)
ELSE_VERBOSE("Pipeline Cache created.");
DEBUG("Created Device '{}' Successfully", m_Name);
} }
Device::~Device() Device::~Device()
{ {
m_Device.destroy(m_PipelineCache, nullptr);
if (m_Allocator) if (m_Allocator)
{ {
vmaDestroyAllocator(m_Allocator); vmaDestroyAllocator(m_Allocator);
@ -110,6 +128,19 @@ Device::GetQueue(const u32 familyIndex, const u32 queueIndex) const
return queue; return queue;
} }
eastl::vector<u8>
Device::DumpPipelineCache() const
{
usize pipelineCacheSize = 0;
vk::Result result = m_Device.getPipelineCacheData(m_PipelineCache, &pipelineCacheSize, nullptr);
ERROR_IF(Failed(result), "Pipeline Cache data fetch failed. Cause: {}", result);
eastl::vector<u8> pipelineCacheData(pipelineCacheSize);
result = m_Device.getPipelineCacheData(m_PipelineCache, &pipelineCacheSize, pipelineCacheData.data());
ERROR_IF(Failed(result), "Pipeline Cache data fetch failed. Cause: {}", result);
return pipelineCacheData;
}
Device::Device(Device &&other) noexcept Device::Device(Device &&other) noexcept
: m_Name(std::move(other.m_Name)) : m_Name(std::move(other.m_Name))
, m_PhysicalDevice(Take(other.m_PhysicalDevice)) , m_PhysicalDevice(Take(other.m_PhysicalDevice))

View File

@ -8,6 +8,7 @@
#include "global.h" #include "global.h"
#include <EASTL/vector.h> #include <EASTL/vector.h>
#include <EASTL/span.h>
struct QueueAllocation; struct QueueAllocation;
struct Context; struct Context;
@ -27,14 +28,19 @@ struct Device final
vk::PhysicalDevice m_PhysicalDevice = nullptr; vk::PhysicalDevice m_PhysicalDevice = nullptr;
vk::Device m_Device = nullptr; vk::Device m_Device = nullptr;
VmaAllocator m_Allocator = nullptr; VmaAllocator m_Allocator = nullptr;
vk::PipelineCache m_PipelineCache = nullptr;
template <typename T> template <typename T>
requires vk::isVulkanHandleType<T>::value void SetName(const T &object, cstr name) const; requires vk::isVulkanHandleType<T>::value void SetName(const T &object, cstr name) const;
[[nodiscard]] vk::Queue GetQueue(u32 familyIndex, u32 queueIndex) const; [[nodiscard]] vk::Queue GetQueue(u32 familyIndex, u32 queueIndex) const;
[[nodiscard]] eastl::vector<u8> DumpPipelineCache() const;
// Ctor/Dtor // Ctor/Dtor
Device(const Context *context, PhysicalDevice *physicalDevice, Features *enabledFeatures, Device(const Context *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
const eastl::vector<QueueAllocation> &queueAllocations, NameString &&name); const eastl::vector<QueueAllocation> &queueAllocations, NameString &&name);
Device(const Context *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
const eastl::vector<QueueAllocation> &queueAllocations, eastl::span<u8> &&pipelineCacheData, NameString &&name);
~Device(); ~Device();
// Move // Move

View File

@ -84,7 +84,54 @@ ReadFile(cstr fileName)
outputVec.resize(nextSize); outputVec.resize(nextSize);
memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data()); memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data());
totalRead = nextSize; totalRead = nextSize;
} while (readCount == 1024); } while (readCount == buffer.size());
return outputVec; return outputVec;
} }
eastl::vector<u8>
ReadFileBytes(cstr fileName, bool errorOnFail)
{
FILE *filePtr = fopen(fileName, "rb");
if (!filePtr)
{
ERROR_IF(errorOnFail, "Invalid open (r) of {}. Cause: {}", fileName, errno);
return {};
}
eastl::vector<u8> outputVec;
eastl::array<u8, 4096> buffer{};
usize totalRead = 0;
usize readCount;
do
{
readCount = fread(buffer.data(), sizeof(u8), buffer.size(), filePtr);
const auto nextSize = totalRead + readCount;
outputVec.resize(nextSize);
memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data());
totalRead = nextSize;
} while (readCount == buffer.size());
(void)fclose(filePtr);
return outputVec;
}
bool
WriteFileBytes(cstr fileName, eastl::span<u8> data)
{
FILE *filePtr = fopen(fileName, "wb");
if (!filePtr)
{
ERROR("Invalid open (w) of {}. Cause: {}", fileName, errno);
return false;
}
const usize written = fwrite(data.data(), sizeof(u8), data.size(), filePtr);
(void)fclose(filePtr);
return written == data.size();
}

View File

@ -8,6 +8,8 @@
#include "global.h" #include "global.h"
#include "queue_allocation.h" #include "queue_allocation.h"
#include "EASTL/span.h"
#include <EASTL/vector.h> #include <EASTL/vector.h>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
@ -17,6 +19,8 @@ class PhysicalDevices;
PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices); PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices);
QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice); QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice);
eastl::vector<u32> ReadFile(cstr fileName); eastl::vector<u32> ReadFile(cstr fileName);
eastl::vector<u8> ReadFileBytes(cstr fileName, bool errorOnFail = true);
bool WriteFileBytes(cstr fileName, eastl::span<u8> data);
#define AbortIfFailed(RESULT) \ #define AbortIfFailed(RESULT) \
do \ do \

View File

@ -29,7 +29,7 @@
#include <filesystem> #include <filesystem>
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3; constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
constexpr auto MODEL_FILE = "model/DamagedHelmet.glb"; constexpr auto PIPELINE_CACHE_FILE = "PipelineCacheData.bin";
struct Camera struct Camera
{ {
@ -127,8 +127,10 @@ main(int, char **)
}, },
}; };
auto pipelineCacheData = ReadFileBytes(PIPELINE_CACHE_FILE, false);
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse); QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"}; Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, pipelineCacheData, "Primary Device"};
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0); vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&window, &device, "Primary Chain"}; Swapchain swapchain = {&window, &device, "Primary Chain"};
GpuResourceManager resourceManager = {&device, 1000}; GpuResourceManager resourceManager = {&device, 1000};
@ -568,6 +570,9 @@ main(int, char **)
AbortIfFailed(device.m_Device.waitIdle()); AbortIfFailed(device.m_Device.waitIdle());
pipelineCacheData = device.DumpPipelineCache();
ERROR_IF(!WriteFileBytes(PIPELINE_CACHE_FILE, pipelineCacheData), "Pipeline Cache incorrectly written");
gui::Destroy(&device); gui::Destroy(&device);
for (auto &depthImage : depthImages) for (auto &depthImage : depthImages)