Added bindless descriptor management swapping function + hooked it up in current renderer

This commit is contained in:
antopilo
2025-05-01 23:26:28 -04:00
parent e8e713253e
commit 060d5b9c6f
6 changed files with 122 additions and 57 deletions

View File

@@ -60,19 +60,19 @@ public:
cmd.DrawTexturedQuad(proj * view * gizmoTransform, TextureManager::Get()->GetTexture2("Resources/Gizmos/Camera.png"), Engine::GetProject()->Settings.PrimaryColor);
});
previewViewport->GetOnLineDraw().AddStatic([&, componentPtr](DebugCmd& cmd)
{
auto& cam = cmd.GetScene()->m_EditorCamera;
Matrix4 initialTransform = Matrix4(1.0f);
initialTransform = glm::translate(initialTransform, cam->Translation);
const float aspectRatio = cam->AspectRatio;
const float fov = cam->Fov;
Matrix4 clampedProj = glm::perspectiveFov(glm::radians(fov), 9.0f * aspectRatio, 9.0f, 0.05f, 3.0f);
Matrix4 boxTransform = glm::translate(scene->GetCurrentCamera()->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix * glm::inverse(clampedProj);
lineCmd.DrawBox(proj * boxTransform, Color(1, 0, 0, 1.0f), 1.5f, false);
});
previewViewport->GetOnLineDraw().AddStatic([&, componentPtr](DebugLineCmd& cmd)
{
//auto& cam = cmd.GetScene()->m_EditorCamera;
//Matrix4 initialTransform = Matrix4(1.0f);
//initialTransform = glm::translate(initialTransform, cam->Translation);
//
//const float aspectRatio = cam->AspectRatio;
//const float fov = cam->Fov;
//
//Matrix4 clampedProj = glm::perspectiveFov(glm::radians(fov), 9.0f * aspectRatio, 9.0f, 0.05f, 3.0f);
//Matrix4 boxTransform = glm::translate(scene->GetCurrentCamera()->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix * glm::inverse(clampedProj);
//cmd.DrawBox(proj * boxTransform, Color(1, 0, 0, 1.0f), 1.5f, false);
});
vkRenderer.RegisterSceneViewport(scene->Shared(), previewViewport->GetID());
}

View File

@@ -1,10 +1,13 @@
#include "BindlessDescriptor.h"
#include "Nuake/Core/Logger.h"
#include "VulkanAllocator.h"
#include "VulkanRenderer.h"
#include "VulkanInit.h"
#include "DescriptorLayoutBuilder.h"
using namespace Nuake;
std::string GetResourceTypeName(ResourceType type)
@@ -80,12 +83,12 @@ Descriptor::Descriptor(Ref<AllocatedBuffer> buffer, VkDescriptorSetLayout layout
vkUpdateDescriptorSets(vk.GetDevice(), 1, &write, 0, nullptr);
}
BindlessDescriptor::BindlessDescriptor(ResourceType type, BindlessInfo& info)
BindlessDescriptor::BindlessDescriptor(ResourceType type, BindlessInfo& info) :
Info(info),
Type(type)
{
// Create a buffer that holds for N frame in flights of data
const std::string& resourceName = GetResourceTypeName(type);
// Build descriptor layout
DescriptorLayoutBuilder builder;
switch (type)
@@ -123,16 +126,42 @@ BindlessDescriptor::BindlessDescriptor(ResourceType type, BindlessInfo& info)
}
}
void BindlessDescriptor::WriteToBuffer(int32_t frameIndex, void* data, size_t size)
{
int currentFrame = frameIndex % FRAME_OVERLAP;
auto& desc = Descriptors[currentFrame];
const size_t offsetSize = Info.ResourceCount[Type] * Info.ResourceElementSize[Type];
size_t offset = currentFrame * offsetSize;
memcpy(desc.DataPtr, data, size);
}
void BindlessDescriptor::Swap(int32_t frameIndex)
{
int currentFrame = frameIndex % FRAME_OVERLAP;
int nextFrame = (frameIndex + 1) % FRAME_OVERLAP;
auto& desc = Descriptors[currentFrame];
auto& nextDesc = Descriptors[nextFrame];
// memcpy from currentFrame to next frame
memcpy(desc.DataPtr, nextDesc.DataPtr, desc.Size);
}
ResourceDescriptors::ResourceDescriptors(const ResourceDescriptorsLimits& limits)
{
struct View
{
int myView;
int dat2;
};
AddResourceDescriptors<ResourceType::View, View>(limits.MaxView);
//AddResourceDescriptors<ResourceType::Material>(limits.MaxMaterial);
//AddResourceDescriptors<ResourceType::Texture>(limits.MaxTexture);
//AddResourceDescriptors<ResourceType::Light>(limits.MaxLight);
//AddResourceDescriptors<ResourceType::Sampler>(limits.MaxSampler);
}
void ResourceDescriptors::Swap(int32_t frameIndex)
{
for (auto& [type, desc] : Descriptors)
{
desc.Swap(frameIndex);
Logger::Log("Swapped: " + GetResourceTypeName(type));
}
}

View File

@@ -37,7 +37,7 @@ namespace Nuake
// A partition of the buffer in BindlessDescriptor
class Descriptor
{
private:
public:
uint8_t* DataPtr;
size_t Size;
size_t Offset;
@@ -49,8 +49,11 @@ namespace Nuake
std::map<UUID, int> SlotMapping;
std::vector<DescriptorSlot> Slots;
public:
Descriptor(Ref<AllocatedBuffer> buffer, VkDescriptorSetLayout layout, uint8_t* ptr, size_t offset, size_t size, BindlessInfo& info);
Descriptor() = default;
~Descriptor() = default;
int32_t LoadResource(const UUID& id);
@@ -64,13 +67,24 @@ namespace Nuake
Ref<AllocatedBuffer> Buffer;
std::vector<Descriptor> Descriptors;
VkDescriptorSetLayout DescriptorLayout;
BindlessInfo Info;
ResourceType Type;
public:
// Delete copy
BindlessDescriptor(const BindlessDescriptor&) = delete;
BindlessDescriptor& operator=(const BindlessDescriptor&) = delete;
// Allow move
BindlessDescriptor(BindlessDescriptor&&) = default;
BindlessDescriptor& operator=(BindlessDescriptor&&) = default;
BindlessDescriptor(ResourceType type, BindlessInfo& info);
BindlessDescriptor() = default;
~BindlessDescriptor() = default;
void QueueCopy(const size_t frameIndex, const size_t offset, const size_t size, const void* data);
void WriteToBuffer(int32_t frameIndex, void* data, size_t size);
void Swap(int32_t frameIndex);
};
struct ResourceDescriptorsLimits
@@ -82,6 +96,12 @@ namespace Nuake
size_t MaxSampler;
};
struct View
{
int myView;
int dat2;
};
// Contains all buffers per resource
class ResourceDescriptors
{
@@ -92,12 +112,21 @@ namespace Nuake
ResourceDescriptors(const ResourceDescriptorsLimits& limits);
~ResourceDescriptors() = default;
void Swap(int32_t frameIndex);
template<ResourceType T>
void UpdateBuffer(int32_t frameIndex, void* data, size_t size)
{
auto& descriptor = Descriptors[T];
descriptor.WriteToBuffer(frameIndex, data, size);
}
template<ResourceType T, typename S>
void AddResourceDescriptors(const size_t size)
{
Info.ResourceElementSize[T] = sizeof(S);
Info.ResourceCount[T] = size;
//Descriptors[T] = BindlessDescriptor(T, Info);
Descriptors[T] = BindlessDescriptor(T, Info);
}
};
}

View File

@@ -12,6 +12,8 @@
#include "Nuake/Rendering/Vulkan/VulkanImage/VulkanImage.h"
#include "Nuake/Rendering/Vulkan/VulkanRenderer.h"
#include "Nuake/Rendering/Vulkan/BindlessDescriptor.h"
#include <volk/volk.h>
#include <stack>
@@ -106,6 +108,8 @@ namespace Nuake
};
private:
Scope<ResourceDescriptors> resourceDescriptors;
FrameData frameData[FRAME_OVERLAP];
bool isDirty = false;
@@ -207,6 +211,8 @@ namespace Nuake
void QueueDeletion(CleanUpStack func);
void CleanUp(uint32_t frame);
void Swap(uint32_t frame);
private:
void CreateBindlessLayout();
CleanUpStack& GetFrameCleanUpStack(uint32_t frame);

View File

@@ -880,6 +880,8 @@ void VkRenderer::EndDraw()
// Increase the number of frames drawn
FrameNumber++;
GPUResources::Get().Swap(FrameNumber);
}
void VkRenderer::DrawImgui(VkCommandBuffer cmd, VkImageView targetImageView)

View File

@@ -4,7 +4,6 @@
#include "GPUManaged.h"
#include "VulkanInit.h"
#include "BindlessDescriptor.h"
using namespace Nuake;
@@ -45,43 +44,38 @@ void GPUResources::Init()
VulkanUtil::SetDebugName(ModelDescriptorLayout, "ModelDescriptorLayout");
}
VkDescriptorSet descriptorSets[FRAME_OVERLAP];
Ref<AllocatedBuffer> bigBuffer = CreateBuffer(sizeof(Matrix4) * MAX_MODEL_MATRIX * FRAME_OVERLAP, BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST, MemoryUsage::CPU_TO_GPU, "BigBuffer");
for (int i = 0; i < FRAME_OVERLAP; i++)
ResourceDescriptorsLimits limits
{
auto& allocator = vk.GetDescriptorAllocator();
descriptorSets[i] = allocator.Allocate(device, ModelDescriptorLayout);
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = bigBuffer->GetBuffer();
bufferInfo.offset = sizeof(Matrix4) * MAX_MODEL_MATRIX * i;
bufferInfo.range = sizeof(Matrix4) * MAX_MODEL_MATRIX;
VkWriteDescriptorSet write{};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.dstSet = descriptorSets[i];
write.dstBinding = 0;
write.dstArrayElement = 0;
write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
write.descriptorCount = 1;
write.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(device, 1, &write, 0, nullptr);
.MaxView = 1000,
.MaxMaterial = 1000,
.MaxTexture = 1000,
.MaxLight = 1000,
.MaxSampler = 1000,
};
resourceDescriptors = CreateScope<ResourceDescriptors>(limits);
View testData
{
.myView = 1,
.dat2 = 2
};
std::vector<View> testDataVector;
testDataVector.reserve(limits.MaxView);
for (int i = 0; i < limits.MaxView; i++)
{
testDataVector.push_back(testData);
}
//// Update the relevant part
//void* mappedData;
//vmaMapMemory(VulkanAllocator::Get().GetAllocator(), (bigBuffer->GetAllocation()), &mappedData);
resourceDescriptors->UpdateBuffer<ResourceType::View>(0, testDataVector.data(), testDataVector.size());
//void* mappedPointer = 0;
//int frameIndex = 1;
////uint8_t* frameData = static_cast<uint8_t*>(bigBuffer) + (frameIndex * sizeof(Matrix4) * MAX_MODEL_MATRIX);
testDataVector[0].myView = 1337;
resourceDescriptors->UpdateBuffer<ResourceType::View>(1, testDataVector.data(), testDataVector.size());
//int data = 2;
//// Now copy into the correct frame
//memcpy(frameData, &data, sizeof(Matrix4) * MAX_MODEL_MATRIX);
//vmaUnmapMemory(VulkanAllocator::Get().GetAllocator(), bigBuffer->GetAllocation());
resourceDescriptors->Swap(1);
resourceDescriptors->Swap(0);
resourceDescriptors->UpdateBuffer<ResourceType::View>(1, testDataVector.data(), testDataVector.size());
resourceDescriptors->Swap(0);
}
Ref<AllocatedBuffer> GPUResources::CreateBuffer(size_t size, BufferUsage flags, MemoryUsage usage, const std::string& name)
@@ -692,6 +686,11 @@ void GPUResources::CleanUp(uint32_t frame)
}
}
void GPUResources::Swap(uint32_t frame)
{
resourceDescriptors->Swap(frame);
}
CleanUpStack& GPUResources::GetFrameCleanUpStack(uint32_t frame)
{
return DeletionQueue[frame % FRAME_OVERLAP];