15 Commits

Author SHA1 Message Date
a.pilote
499540b23d Merge branch 'vulkan-dev' 2025-09-02 23:03:53 -04:00
a.pilote
e9e8d906b1 Push bindings.json 2025-09-02 22:59:59 -04:00
antopilo
1417df96d1 Renderer is now using new buffer management system 2025-05-04 22:33:47 -04:00
antopilo
f57393d354 Fixed validation errors 2025-05-04 12:11:37 -04:00
antopilo
f88c76445f Moved GPU Data structs into its own header and hooked them up in the bindless descriptor management system 2025-05-03 12:13:56 -04:00
antopilo
fe89b84222 Added automated reflection based json serialization for reflected components 2025-05-03 11:56:59 -04:00
Antoine Pilote
2a9b4de5eb Merge branch 'vulkan-dev' of https://github.com/antopilo/nuake into vulkan-dev 2025-05-02 16:50:50 -04:00
Antoine Pilote
70141a7ee6 Added catch2 2025-05-02 16:50:34 -04:00
antopilo
060d5b9c6f Added bindless descriptor management swapping function + hooked it up in current renderer 2025-05-01 23:26:28 -04:00
antopilo
e8e713253e Fixed compilation errors 2025-04-29 22:30:56 -04:00
antopilo
6f9f3a96e2 NEw splash screen + can now see editor cam in camera preview 2025-04-29 22:30:44 -04:00
antopilo
993bc3ae43 Fixed latest compilation problems 2025-03-22 19:21:03 -04:00
Antoine Pilote
4d34b9978a Update FUNDING.yml 2025-02-01 01:20:58 -05:00
Antoine Pilote
4661c1f00e Update LICENSE 2024-12-06 22:14:24 -05:00
Antoine Pilote
b6721d036a Merge pull request #94 from antopilo/develop
Bumped to develop
2024-12-02 17:05:08 -05:00
26 changed files with 26697 additions and 346 deletions

3
.github/FUNDING.yml vendored
View File

@@ -1,9 +1,8 @@
# These are supported funding model platforms
patreon: # Replace with a single Patreon username
patreon: nuakeengine # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: antopilo # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 152 KiB

View File

@@ -5,6 +5,7 @@
#include "Nuake/Core/Core.h"
#include "Nuake/Rendering/Vulkan/SceneViewport.h"
#include "Nuake/Rendering/Vulkan/DebugCmd.h"
class CameraPanel
{
@@ -22,6 +23,56 @@ public:
previewViewport = vkRenderer.CreateViewport(viewId, { 200, 200 });
previewViewport->SetDebugName("CameraPreviewViewport");
previewViewport->GetOnDebugDraw().AddStatic([&, componentPtr](DebugCmd& cmd)
{
Matrix4 transform = Matrix4(1.0f);
auto& cam = cmd.GetScene()->m_EditorCamera;
Matrix4 initialTransform = Matrix4(1.0f);
initialTransform = glm::translate(initialTransform, cam->Translation);
Matrix4 gizmoTransform = initialTransform;
gizmoTransform = glm::inverse(componentPtr->CameraInstance->GetTransform());
gizmoTransform[3] = initialTransform[3];
auto view = componentPtr->CameraInstance->GetTransform();
auto proj = componentPtr->CameraInstance->GetPerspective();
static auto getGizmoScale = [](const Vector3& camPosition, const Nuake::Vector3& position) -> float
{
float distance = Distance(camPosition, position);
constexpr float ClosestDistance = 3.5f;
if (distance < ClosestDistance)
{
float fraction = distance / ClosestDistance;
return fraction;
}
return 1.0f;
};
Vector3 cameraPosition = componentPtr->CameraInstance->Translation;
const Vector3 gizmoSize = Vector3(Engine::GetProject()->Settings.GizmoSize);
gizmoTransform = glm::scale(gizmoTransform, gizmoSize * getGizmoScale(cameraPosition, initialTransform[3]));
cmd.DrawTexturedQuad(proj * view * gizmoTransform, TextureManager::Get()->GetTexture2("Resources/Gizmos/Camera.png"), Engine::GetProject()->Settings.PrimaryColor);
});
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,6 +1,6 @@
MIT License
Copyright (c) 2023 Antoine Pilote
Copyright (c) 2023-2025 Antoine Pilote
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@@ -1,16 +1,21 @@
#include "BindlessDescriptor.h"
#include "Nuake/Core/Logger.h"
#include "VulkanAllocator.h"
#include "VulkanRenderer.h"
#include "VulkanInit.h"
#include "DescriptorLayoutBuilder.h"
#include "GPUData/GPUData.h"
using namespace Nuake;
std::string GetResourceTypeName(ResourceType type)
{
switch (type)
{
case ResourceType::Transform: return "Transform";
case ResourceType::View: return "View";
case ResourceType::Material: return "Material";
case ResourceType::Texture: return "Texture";
@@ -54,8 +59,8 @@ int32_t Descriptor::GetResourceSlot(const UUID& id) const
return 0; // Resource not found
}
Descriptor::Descriptor(Ref<AllocatedBuffer> buffer, VkDescriptorSetLayout layout, uint8_t* ptr, size_t offset, size_t size, BindlessInfo& info)
: DataPtr(ptr), Offset(offset), Size(size), Info(info)
Descriptor::Descriptor(Ref<AllocatedBuffer> buffer, VkDescriptorSetLayout layout, uint8_t* ptr, size_t offset, size_t size, BindlessInfo& info, uint32_t bindingSlot)
: DataPtr(ptr), Offset(offset), Size(size), Info(info), BindingSlot(bindingSlot)
{
auto& vk = VkRenderer::Get();
auto& allocator = VkRenderer::Get().GetDescriptorAllocator();
@@ -80,8 +85,15 @@ Descriptor::Descriptor(Ref<AllocatedBuffer> buffer, VkDescriptorSetLayout layout
vkUpdateDescriptorSets(vk.GetDevice(), 1, &write, 0, nullptr);
}
void Descriptor::Bind(VkCommandBuffer cmd, VkPipelineLayout layout)
{
Cmd command(cmd);
command.BindDescriptorSet(layout, DescriptorSet, BindingSlot);
}
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);
@@ -90,14 +102,15 @@ BindlessDescriptor::BindlessDescriptor(ResourceType type, BindlessInfo& info)
DescriptorLayoutBuilder builder;
switch (type)
{
case ResourceType::View:
case ResourceType::Material:
case ResourceType::Light:
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
break;
case ResourceType::Texture:
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
break;
case ResourceType::Sampler:
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLER);
break;
default:
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
break;
}
DescriptorLayout = builder.Build(VkRenderer::Get().GetDevice(), VK_SHADER_STAGE_ALL_GRAPHICS);
@@ -106,10 +119,11 @@ BindlessDescriptor::BindlessDescriptor(ResourceType type, BindlessInfo& info)
// Create buffer and map, CPU -> GPU since we will writing to it directly
// Size of buffer is: size_of(ResourceType) * FRAME_OVERLAP since 1 buffer will hold N Frames in flight
// TODO(antopilo): move mapped pointer inside buffer directly
const BufferUsage usage = BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST;
const BufferUsage usage = BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST | BufferUsage::TRANSFER_SRC;
const MemoryUsage memoryUsage = MemoryUsage::CPU_TO_GPU;
const size_t size = info.ResourceElementSize[type] * info.ResourceCount[type];
const size_t totalSize = size * FRAME_OVERLAP;
Buffer = CreateRef<AllocatedBuffer>(resourceName + "GPUBuffer", totalSize, usage, memoryUsage);
// Map to a host-visible pointer
@@ -119,20 +133,70 @@ BindlessDescriptor::BindlessDescriptor(ResourceType type, BindlessInfo& info)
{
const size_t offset = i * size;
uint8_t* partitionStart = static_cast<uint8_t*>(mappedData) + offset;
Descriptors.emplace_back(Descriptor(Buffer, DescriptorLayout, partitionStart, offset, size));
Descriptors.emplace_back(Buffer, DescriptorLayout, partitionStart, offset, size, info, Info.ResourceBindingSlot[Type]);
}
}
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;
LastWriteSize = size;
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(nextDesc.DataPtr, desc.DataPtr, LastWriteSize);
}
void BindlessDescriptor::Bind(VkCommandBuffer cmd, int32_t frameIndex, VkPipelineLayout layout)
{
int currentFrame = frameIndex % FRAME_OVERLAP;
auto& desc = Descriptors[currentFrame];
desc.Bind(cmd, layout);
}
ResourceDescriptors::ResourceDescriptors(const ResourceDescriptorsLimits& limits)
{
struct View
AddResourceDescriptors<ResourceType::Transform, Matrix4>(limits.MaxTransform, 0);
AddResourceDescriptors<ResourceType::Sampler, VkDescriptorImageInfo>(limits.MaxSampler, 2);
AddResourceDescriptors<ResourceType::Material, MaterialBufferStruct>(limits.MaxMaterial, 3);
AddResourceDescriptors<ResourceType::Texture, VkDescriptorImageInfo>(limits.MaxTexture, 4);
AddResourceDescriptors<ResourceType::Light, LightData>(limits.MaxLight, 5);
AddResourceDescriptors<ResourceType::View, CameraView>(limits.MaxView, 6);
}
void ResourceDescriptors::Swap(int32_t frameIndex)
{
for (auto& [type, desc] : Descriptors)
{
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);
}
desc.Swap(frameIndex);
}
}
void ResourceDescriptors::Bind(VkCommandBuffer cmd, int32_t frame, VkPipelineLayout layout)
{
/*
for (auto& [type, desc] : Descriptors)
{
desc.Bind(cmd, frame, layout);
}
*/
Descriptors[ResourceType::Transform].Bind(cmd, frame, layout);
Descriptors[ResourceType::Material].Bind(cmd, frame, layout);
Descriptors[ResourceType::Light].Bind(cmd, frame, layout);
Descriptors[ResourceType::View].Bind(cmd, frame, layout);
}

View File

@@ -14,6 +14,7 @@ namespace Nuake
{
View,
Material,
Transform,
Texture,
Light,
Sampler
@@ -24,6 +25,7 @@ namespace Nuake
std::map<ResourceType, size_t> ResourceElementSize;
std::map<ResourceType, size_t> ResourceCount;
std::map<ResourceType, AllocatedBuffer> ResourceBuffers;
std::map<ResourceType, uint32_t> ResourceBindingSlot;
};
class DescriptorSlot
@@ -37,10 +39,11 @@ namespace Nuake
// A partition of the buffer in BindlessDescriptor
class Descriptor
{
private:
public:
uint8_t* DataPtr;
size_t Size;
size_t Offset;
uint32_t BindingSlot;
private:
BindlessInfo& Info;
@@ -50,12 +53,14 @@ namespace Nuake
std::vector<DescriptorSlot> Slots;
public:
Descriptor(Ref<AllocatedBuffer> buffer, VkDescriptorSetLayout layout, uint8_t* ptr, size_t offset, size_t size, BindlessInfo& info);
Descriptor(Ref<AllocatedBuffer> buffer, VkDescriptorSetLayout layout, uint8_t* ptr, size_t offset, size_t size, BindlessInfo& info, uint32_t bindingSlot);
Descriptor() = default;
~Descriptor() = default;
int32_t LoadResource(const UUID& id);
int32_t GetResourceSlot(const UUID& id);
int32_t GetResourceSlot(const UUID& id) const;
void Bind(VkCommandBuffer cmd, VkPipelineLayout layout);
};
// Contains buffer for N frames of a resource type
@@ -65,17 +70,37 @@ namespace Nuake
Ref<AllocatedBuffer> Buffer;
std::vector<Descriptor> Descriptors;
VkDescriptorSetLayout DescriptorLayout;
BindlessInfo Info;
ResourceType Type;
size_t LastWriteSize = 0;
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);
void Bind(VkCommandBuffer cmd, int32_t frameIndex, VkPipelineLayout layout);
};
struct ResourceDescriptorDef
{
size_t Size;
uint32_t Slot;
};
struct ResourceDescriptorsLimits
{
size_t MaxTransform;
size_t MaxView;
size_t MaxMaterial;
size_t MaxTexture;
@@ -83,6 +108,12 @@ namespace Nuake
size_t MaxSampler;
};
struct View
{
int myView;
int dat2;
};
// Contains all buffers per resource
class ResourceDescriptors
{
@@ -93,12 +124,24 @@ 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)
void AddResourceDescriptors(const size_t size, const uint32_t bindingSlot)
{
Info.ResourceElementSize[T] = sizeof(S);
Info.ResourceCount[T] = size;
Descriptors[T] = BindlessDescriptor(T, (size_t)sizeof(S) * size);
Info.ResourceBindingSlot[T] = bindingSlot;
Descriptors[T] = BindlessDescriptor(T, Info);
}
void Bind(VkCommandBuffer cmd, int32_t frame, VkPipelineLayout layout);
};
}

View File

@@ -1,5 +1,6 @@
#include "Cmd.h"
#include "VulkanAllocatedBuffer.h"
#include "VkResources.h"
using namespace Nuake;
@@ -18,6 +19,12 @@ void Cmd::BindPipeline(VkPipeline pipeline) const
vkCmdBindPipeline(CmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
}
void Cmd::BindSceneData(VkPipelineLayout pipelineLayout)
{
auto& res = GPUResources::Get();
res.BindSceneData(CmdBuffer, pipelineLayout);
}
void Cmd::SetViewport(const Vector2 & size) const
{
VkViewport viewport = {};

View File

@@ -57,6 +57,7 @@ namespace Nuake
void DebugMarker(const std::string& name, Color color = Color(1, 0, 0, 1));
void BindPipeline(VkPipeline pipeline) const;
void BindSceneData(VkPipelineLayout pipelineLayout);
void SetViewport(const Vector2& size) const;
void SetScissor(const Vector2& size) const;
void ClearColorImage(Ref<VulkanImage> img, Color color = Color(0, 0, 0, 1)) const;

View File

@@ -0,0 +1,66 @@
#pragma once
#include "Nuake/Core/Maths.h"
#include <array>
namespace Nuake
{
struct TransformData
{
std::array<Matrix4, 3000> Data;
};
struct MaterialBufferStruct
{
int HasAlbedo;
Vector3 AlbedoColor;
int HasNormal;
int HasMetalness;
int HasRoughness;
int HasAO;
float MetalnessValue;
float RoughnessValue;
float AoValue;
uint32_t AlbedoTextureId;
uint32_t NormalTextureId;
uint32_t MetalnessTextureId;
uint32_t RoughnessTextureId;
uint32_t AoTextureId;
int SamplerType;
int ReceiveShadow;
int CastShadow;
int Unlit;
int AlphaScissor;
int pad[3];
};
struct LightData
{
Vector3 Position;
int Type;
Vector4 Color;
Vector3 Direction;
float OuterConeAngle;
float InnerConeAngle;
int CastShadow;
int ShadowMapTextureId[4];
int TransformId[4];
float pad[2];
};
struct CameraView
{
Matrix4 View;
Matrix4 Projection;
Matrix4 ViewProjection;
Matrix4 InverseView;
Matrix4 InverseProjection;
Vector3 Position;
float Near;
float Far;
float pad;
float pad2;
float pad3;
//char padding[64]; // 124 bytes to reach 128 bytes
};
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <volk/volk.h>
namespace Nuake
{
enum class SamplerType
{
Linear,
Nearest
};
class Sampler
{
private:
VkSampler vkSampler;
float maxAnisotropy;
public:
Sampler(SamplerType samplerType);
~Sampler();
};
}

View File

@@ -34,16 +34,13 @@ ShadowRenderPipeline::ShadowRenderPipeline()
shadowPass.SetShaders(shaderMgr.GetShader("shadow_vert"), shaderMgr.GetShader("shadow_frag"));
shadowPass.SetPushConstant<GBufferConstant>(gbufferConstant);
shadowPass.SetPreRender([&](PassRenderContext& ctx) {
auto& layout = ctx.renderPass->PipelineLayout;
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
Cmd& cmd = ctx.commandBuffer;
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
shadowPass.SetRender([&](PassRenderContext& ctx) {
auto& cmd = ctx.commandBuffer;
@@ -380,14 +377,11 @@ void SceneRenderPipeline::RecreatePipeline()
{
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
Cmd& cmd = ctx.commandBuffer;
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
gBufferPass.SetRender([&](PassRenderContext& ctx)
{
@@ -490,12 +484,9 @@ void SceneRenderPipeline::RecreatePipeline()
Cmd& cmd = ctx.commandBuffer;
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
// Bind noise kernel
cmd.BindDescriptorSet(layout, res.SSAOKernelDescriptor, 7);
@@ -532,12 +523,9 @@ void SceneRenderPipeline::RecreatePipeline()
Cmd& cmd = ctx.commandBuffer;
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
blurConstant.sourceTextureID = res.GetBindlessTextureID(SSAOOutput->GetID());
blurConstant.sourceSize = SSAOOutput->GetSize();
@@ -608,12 +596,9 @@ void SceneRenderPipeline::RecreatePipeline()
auto& res = GPUResources::Get();
// Bindless
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
// Inputs
shadingConstant.AlbedoTextureID = res.GetBindlessTextureID(GBufferAlbedo->GetID());
@@ -664,12 +649,9 @@ void SceneRenderPipeline::RecreatePipeline()
auto& res = GPUResources::Get();
// Bindless
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
// Inputs
tonemapConstant.Exposure = ctx.scene->GetEnvironment()->Exposure;
@@ -702,14 +684,9 @@ void SceneRenderPipeline::RecreatePipeline()
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
//ctx.renderPass->SetClearColor({0, 0, 0, 0});
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
volumetricPass.SetRender([&](PassRenderContext& ctx)
{
@@ -759,13 +736,9 @@ void SceneRenderPipeline::RecreatePipeline()
Cmd& cmd = ctx.commandBuffer;
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
volumetricBlurPass.SetRender([&](PassRenderContext& ctx)
{
@@ -792,13 +765,9 @@ void SceneRenderPipeline::RecreatePipeline()
Cmd& cmd = ctx.commandBuffer;
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
volumetricCombinePass.SetRender([&](PassRenderContext& ctx)
{
@@ -830,13 +799,9 @@ void SceneRenderPipeline::RecreatePipeline()
Cmd& cmd = ctx.commandBuffer;
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
gizmoPass.SetRender([&](PassRenderContext& ctx)
{
@@ -855,13 +820,9 @@ void SceneRenderPipeline::RecreatePipeline()
Cmd& cmd = ctx.commandBuffer;
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
gizmoCombinePass.SetRender([&](PassRenderContext& ctx)
{
@@ -891,13 +852,9 @@ void SceneRenderPipeline::RecreatePipeline()
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
// Bindless
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
outlinePass.SetRender([&](PassRenderContext& ctx)
{
@@ -932,12 +889,9 @@ void SceneRenderPipeline::RecreatePipeline()
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
linePass.SetRender([&](PassRenderContext& ctx)
{
@@ -957,12 +911,9 @@ void SceneRenderPipeline::RecreatePipeline()
auto& layout = ctx.renderPass->PipelineLayout;
auto& res = GPUResources::Get();
cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0);
res.BindSceneData(ctx.commandBuffer.GetCmdBuffer(), layout);
cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2);
cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3);
cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4);
cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5);
cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6);
});
lineCombinePass.SetRender([&](PassRenderContext& ctx)
{
@@ -979,7 +930,6 @@ void SceneRenderPipeline::RecreatePipeline()
cmd.DrawIndexed(6);
});
GBufferPipeline.Build();
}

View File

@@ -12,6 +12,9 @@
#include "Nuake/Rendering/Vulkan/VulkanImage/VulkanImage.h"
#include "Nuake/Rendering/Vulkan/VulkanRenderer.h"
#include "Nuake/Rendering/Vulkan/BindlessDescriptor.h"
#include "Nuake/Rendering/Vulkan/GPUData/GPUData.h"
#include <volk/volk.h>
#include <stack>
@@ -20,77 +23,17 @@
namespace Nuake
{
struct ModelData
{
std::array<Matrix4, 3000> Data;
};
// This is what is present on the shader as a structured buffer
struct MaterialBufferStruct
{
int HasAlbedo;
Vector3 AlbedoColor;
int HasNormal;
int HasMetalness;
int HasRoughness;
int HasAO;
float MetalnessValue;
float RoughnessValue;
float AoValue;
uint32_t AlbedoTextureId;
uint32_t NormalTextureId;
uint32_t MetalnessTextureId;
uint32_t RoughnessTextureId;
uint32_t AoTextureId;
int SamplerType;
int ReceiveShadow;
int CastShadow;
int Unlit;
int AlphaScissor;
int pad[3];
};
// This is the *whole* buffer
struct MaterialData
{
std::array<MaterialBufferStruct, 2000> Data;
};
struct LightData
{
Vector3 Position;
int Type;
Vector4 Color;
Vector3 Direction;
float OuterConeAngle;
float InnerConeAngle;
int CastShadow;
int ShadowMapTextureId[4];
int TransformId[4];
float pad[2];
};
struct LightDataContainer
{
std::array<LightData, 100> Data;
};
struct CameraView
{
Matrix4 View;
Matrix4 Projection;
Matrix4 ViewProjection;
Matrix4 InverseView;
Matrix4 InverseProjection;
Vector3 Position;
float Near;
float Far;
float pad;
float pad2;
float pad3;
//char padding[64]; // 124 bytes to reach 128 bytes
};
constexpr uint32_t MAX_MODEL_MATRIX = 3000;
constexpr uint32_t MAX_MATERIAL = 2000;
constexpr uint32_t MAX_TEXTURES = 3000;
@@ -105,7 +48,9 @@ namespace Nuake
VkDescriptorSet TestDescriptorSet;
};
Scope<ResourceDescriptors> resourceDescriptors;
private:
FrameData frameData[FRAME_OVERLAP];
bool isDirty = false;
@@ -143,7 +88,7 @@ namespace Nuake
std::vector<CleanUpStack> DeletionQueue;
public:
ModelData ModelTransforms;
TransformData ModelTransforms;
MaterialData MaterialDataContainer;
LightDataContainer LightDataContainerArray;
@@ -207,6 +152,10 @@ namespace Nuake
void QueueDeletion(CleanUpStack func);
void CleanUp(uint32_t frame);
void Swap(uint32_t frame);
void BindSceneData(VkCommandBuffer cmd, VkPipelineLayout pipeline);
private:
void CreateBindlessLayout();
CleanUpStack& GetFrameCleanUpStack(uint32_t frame);

View File

@@ -27,7 +27,7 @@ AllocatedBuffer::AllocatedBuffer(size_t inSize, BufferUsage inFlags, MemoryUsage
VmaAllocationCreateInfo vmaallocInfo = {};
vmaallocInfo.usage = static_cast<VmaMemoryUsage>(inUsage);
vmaallocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
vmaallocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
MemUsage = inUsage;

View File

@@ -749,6 +749,7 @@ bool VkRenderer::Draw()
VK_CALL(vkWaitForFences(Device, 1, &GetCurrentFrame().RenderFence, true, 1000000000));
if (SurfaceSize != Window::Get()->GetSize())
{
RecreateSwapchain();
@@ -771,6 +772,8 @@ bool VkRenderer::Draw()
VK_CALL(vkResetFences(Device, 1, &GetCurrentFrame().RenderFence));
GPUResources::Get().Swap(FrameNumber);
// Note: this will be the meat of the engine that should be here.
VkCommandBuffer cmd = GetCurrentFrame().CommandBuffer;
VK_CALL(vkResetCommandBuffer(cmd, 0));
@@ -880,6 +883,7 @@ void VkRenderer::EndDraw()
// Increase the number of frames drawn
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,26 @@ 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);
}
.MaxTransform = 3000,
.MaxView = 1000,
.MaxMaterial = 1000,
.MaxTexture = 3000,
.MaxLight = 1000,
.MaxSampler = 2,
};
resourceDescriptors = CreateScope<ResourceDescriptors>(limits);
//// Update the relevant part
//void* mappedData;
//vmaMapMemory(VulkanAllocator::Get().GetAllocator(), (bigBuffer->GetAllocation()), &mappedData);
//void* mappedPointer = 0;
//int frameIndex = 1;
////uint8_t* frameData = static_cast<uint8_t*>(bigBuffer) + (frameIndex * sizeof(Matrix4) * MAX_MODEL_MATRIX);
//int data = 2;
//// Now copy into the correct frame
//memcpy(frameData, &data, sizeof(Matrix4) * MAX_MODEL_MATRIX);
//vmaUnmapMemory(VulkanAllocator::Get().GetAllocator(), bigBuffer->GetAllocation());
//resourceDescriptors->UpdateBuffer<ResourceType::View>(0, testDataVector.data(), testDataVector.size());
//
//testDataVector[0].myView = 1337;
//resourceDescriptors->UpdateBuffer<ResourceType::View>(1, testDataVector.data(), testDataVector.size());
//
//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)
@@ -339,16 +321,6 @@ void GPUResources::CreateBindlessLayout()
VulkanUtil::SetDebugName(CamerasDescriptorLayout, "CamerasDescriptorLayout");
}
ResourceDescriptorsLimits limits
{
.MaxView = 10,
.MaxMaterial = 1,
.MaxTexture = 20,
.MaxLight = 10,
.MaxSampler = 2,
};
ResourceDescriptors descriptors = ResourceDescriptors(limits);
auto allocator = vk.GetDescriptorAllocator();
TexturesDescriptor = allocator.Allocate(device, TexturesDescriptorLayout);
CamerasDescriptor = allocator.Allocate(device, CamerasDescriptorLayout);
@@ -407,7 +379,7 @@ void GPUResources::CreateBindlessLayout()
void GPUResources::RecreateBindlessTextures()
{
// Ideally wed have update bit enabled ondescriptors
//vkQueueWaitIdle(VkRenderer::Get().GPUQueue);
vkQueueWaitIdle(VkRenderer::Get().GPUQueue);
if (!TexturesDescriptor)
{
@@ -451,151 +423,16 @@ void GPUResources::RecreateBindlessCameras()
i++;
}
void* mappedData;
auto allocator = VulkanAllocator::Get().GetAllocator();
vmaMapMemory(allocator, (VkRenderer::Get().GetCurrentFrame().CamerasStagingBuffer->GetAllocation()), &mappedData);
memcpy(mappedData, Cameras.data(), sizeof(CameraView) * Cameras.size());
VkRenderer::Get().GetCurrentFrame().CamerasStagingBuffer->Update();
VkRenderer::Get().ImmediateSubmit([&](VkCommandBuffer cmd) {
VkBufferCopy copy{ 0 };
copy.dstOffset = 0;
copy.srcOffset = 0;
copy.size = sizeof(CameraView) * MAX_CAMERAS;
vkCmdCopyBuffer(cmd, VkRenderer::Get().GetCurrentFrame().CamerasStagingBuffer->GetBuffer(), CamerasBuffer->GetBuffer(), 1, &copy);
CamerasBuffer->Update();
});
vmaUnmapMemory(allocator, VkRenderer::Get().GetCurrentFrame().CamerasStagingBuffer->GetAllocation());
// Update descriptor set for camera
VkDescriptorBufferInfo transformBufferInfo{};
transformBufferInfo.buffer = CamerasBuffer->GetBuffer();
transformBufferInfo.offset = 0;
transformBufferInfo.range = VK_WHOLE_SIZE;
VkWriteDescriptorSet bufferWriteModel = {};
bufferWriteModel.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
bufferWriteModel.pNext = nullptr;
bufferWriteModel.dstBinding = 0;
bufferWriteModel.dstSet = CamerasDescriptor;
bufferWriteModel.descriptorCount = 1;
bufferWriteModel.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bufferWriteModel.pBufferInfo = &transformBufferInfo;
vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &bufferWriteModel, 0, nullptr);
const auto frameIndex = VkRenderer::Get().FrameNumber;
resourceDescriptors->UpdateBuffer<ResourceType::View>(frameIndex, Cameras.data(), Cameras.size() * sizeof(CameraView));
}
void GPUResources::UpdateBuffers()
{
// Tranforms
{
void* mappedData;
vmaMapMemory(VulkanAllocator::Get().GetAllocator(), (VkRenderer::Get().GetCurrentFrame().ModelStagingBuffer->GetAllocation()), &mappedData);
memcpy(mappedData, &ModelTransforms, sizeof(ModelData));
VkRenderer::Get().GetCurrentFrame().ModelStagingBuffer->Update();
VkRenderer::Get().ImmediateSubmit([&](VkCommandBuffer cmd) {
VkBufferCopy copy{ 0 };
copy.dstOffset = 0;
copy.srcOffset = 0;
copy.size = sizeof(ModelData);
vkCmdCopyBuffer(cmd, VkRenderer::Get().GetCurrentFrame().ModelStagingBuffer->GetBuffer(), ModelBuffer->GetBuffer(), 1, &copy);
ModelBuffer->Update();
});
vmaUnmapMemory(VulkanAllocator::Get().GetAllocator(), VkRenderer::Get().GetCurrentFrame().ModelStagingBuffer->GetAllocation());
// Update descriptor set for camera
VkDescriptorBufferInfo transformBufferInfo{};
transformBufferInfo.buffer = ModelBuffer->GetBuffer();
transformBufferInfo.offset = 0;
transformBufferInfo.range = VK_WHOLE_SIZE;
VkWriteDescriptorSet bufferWriteModel = {};
bufferWriteModel.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
bufferWriteModel.pNext = nullptr;
bufferWriteModel.dstBinding = 0;
bufferWriteModel.dstSet = ModelDescriptor;
bufferWriteModel.descriptorCount = 1;
bufferWriteModel.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bufferWriteModel.pBufferInfo = &transformBufferInfo;
vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &bufferWriteModel, 0, nullptr);
}
// Update material buffer
{
void* mappedData;
vmaMapMemory(VulkanAllocator::Get().GetAllocator(), (VkRenderer::Get().GetCurrentFrame().MaterialStagingBuffer->GetAllocation()), &mappedData);
memcpy(mappedData, &MaterialDataContainer, sizeof(MaterialData));
VkRenderer::Get().GetCurrentFrame().MaterialStagingBuffer->Update();
VkRenderer::Get().ImmediateSubmit([&](VkCommandBuffer cmd) {
VkBufferCopy copy{ 0 };
copy.dstOffset = 0;
copy.srcOffset = 0;
copy.size = sizeof(MaterialData);
vkCmdCopyBuffer(cmd, VkRenderer::Get().GetCurrentFrame().MaterialStagingBuffer->GetBuffer(), MaterialBuffer->GetBuffer(), 1, &copy);
MaterialBuffer->Update();
});
vmaUnmapMemory(VulkanAllocator::Get().GetAllocator(), VkRenderer::Get().GetCurrentFrame().MaterialStagingBuffer->GetAllocation());
// Update descriptor set for camera
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = MaterialBuffer->GetBuffer();
bufferInfo.offset = 0;
bufferInfo.range = VK_WHOLE_SIZE;
VkWriteDescriptorSet bufferWrite = {};
bufferWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
bufferWrite.pNext = nullptr;
bufferWrite.dstBinding = 0;
bufferWrite.dstSet = MaterialDescriptor;
bufferWrite.descriptorCount = 1;
bufferWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bufferWrite.pBufferInfo = &bufferInfo;
bufferWrite.pImageInfo = VK_NULL_HANDLE;
vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &bufferWrite, 0, nullptr);
}
// Lights
{
void* mappedData;
vmaMapMemory(VulkanAllocator::Get().GetAllocator(), (VkRenderer::Get().GetCurrentFrame().LightStagingBuffer->GetAllocation()), &mappedData);
memcpy(mappedData, &LightDataContainerArray, sizeof(LightDataContainer));
VkRenderer::Get().GetCurrentFrame().LightStagingBuffer->Update();
VkRenderer::Get().ImmediateSubmit([&](VkCommandBuffer cmd) {
VkBufferCopy copy{ 0 };
copy.dstOffset = 0;
copy.srcOffset = 0;
copy.size = sizeof(LightDataContainer);
vkCmdCopyBuffer(cmd, VkRenderer::Get().GetCurrentFrame().LightStagingBuffer->GetBuffer(), LightBuffer->GetBuffer(), 1, &copy);
LightBuffer->Update();
});
vmaUnmapMemory(VulkanAllocator::Get().GetAllocator(), VkRenderer::Get().GetCurrentFrame().LightStagingBuffer->GetAllocation());
// Update descriptor set for camera
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = LightBuffer->GetBuffer();
bufferInfo.offset = 0;
bufferInfo.range = VK_WHOLE_SIZE;
VkWriteDescriptorSet bufferWrite = {};
bufferWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
bufferWrite.pNext = nullptr;
bufferWrite.dstBinding = 0;
bufferWrite.dstSet = LightsDescriptor;
bufferWrite.descriptorCount = 1;
bufferWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bufferWrite.pBufferInfo = &bufferInfo;
bufferWrite.pImageInfo = VK_NULL_HANDLE;
vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &bufferWrite, 0, nullptr);
}
auto frameIndex = VkRenderer::Get().FrameNumber;
resourceDescriptors->UpdateBuffer<ResourceType::Transform>(frameIndex, ModelTransforms.Data.data(), ModelTransforms.Data.size() * sizeof(Matrix4));
resourceDescriptors->UpdateBuffer<ResourceType::Material>(frameIndex, MaterialDataContainer.Data.data(), MaterialDataContainer.Data.size() * sizeof(MaterialBufferStruct));
resourceDescriptors->UpdateBuffer<ResourceType::Light>(frameIndex, LightDataContainerArray.Data.data(), LightDataContainerArray.Data.size() * sizeof(LightData));
}
std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
@@ -692,6 +529,16 @@ void GPUResources::CleanUp(uint32_t frame)
}
}
void GPUResources::Swap(uint32_t frame)
{
resourceDescriptors->Swap(frame);
}
void GPUResources::BindSceneData(VkCommandBuffer cmd, VkPipelineLayout pipeline)
{
resourceDescriptors->Bind(cmd, VkRenderer::Get().FrameNumber, pipeline);
}
CleanUpStack& GPUResources::GetFrameCleanUpStack(uint32_t frame)
{
return DeletionQueue[frame % FRAME_OVERLAP];

View File

@@ -640,7 +640,7 @@ void VkSceneRenderer::PrepareScenes(const std::vector<Ref<Scene>>& scenes, Rende
gpu.RecreateBindlessCameras();
}
gpu.ModelTransforms = ModelData{ allTransforms };
gpu.ModelTransforms = TransformData{ allTransforms };
gpu.MaterialDataContainer = MaterialData{ allMaterials };
gpu.LightDataContainerArray = LightDataContainer{ allLights };
gpu.LightCount = lightCount;

View File

@@ -85,9 +85,100 @@ namespace Nuake
cursor["file" + displayName] = value.file->GetRelativePath();
}
}
else if (dataType.type() == entt::resolve<std::string>())
{
std::string value = fieldVal.cast<std::string>();
cursor[displayName] = value;
}
else if (auto prop = dataType.prop(HashedFieldPropName::IsEnum); prop)
{
auto enumMeta = dataType.type();
// Fallback to integer value if name not available
cursor[displayName] = static_cast<int>(fieldVal.cast<int>());
}
}
return jsonSnippet;
}
template<IsComponentT T>
void Deserialize(const json& jsonSnippet, T& component)
{
const entt::meta_type meta = entt::resolve<T>();
if (!meta) return;
entt::meta_any metaAny = meta.from_void(static_cast<void*>(&component));
if (!metaAny) return;
const std::string componentName = Component::GetName(meta);
if (!jsonSnippet.contains(componentName)) return;
const json& cursor = jsonSnippet.at(componentName);
for (auto [fst, dataMember] : meta.data())
{
auto propName = dataMember.prop(HashedName::DisplayName);
if (!propName) continue;
const char* displayNameC = *propName.value().try_cast<const char*>();
std::string displayName = displayNameC;
if (!cursor.contains(displayName)) continue;
const entt::meta_type fieldType = dataMember.type();
if (fieldType == entt::resolve<float>())
{
dataMember.set(metaAny, cursor.at(displayName).get<float>());
}
else if (fieldType == entt::resolve<int32_t>())
{
dataMember.set(metaAny, cursor.at(displayName).get<int32_t>());
}
else if (fieldType == entt::resolve<bool>())
{
dataMember.set(metaAny, cursor.at(displayName).get<bool>());
}
else if (fieldType == entt::resolve<Vector2>())
{
Vector2 vec;
vec.x = cursor.at(displayName).at("x").get<float>();
vec.y = cursor.at(displayName).at("y").get<float>();
dataMember.set(metaAny, vec);
}
else if (fieldType == entt::resolve<Vector3>())
{
Vector3 vec;
vec.x = cursor.at(displayName).at("x").get<float>();
vec.y = cursor.at(displayName).at("y").get<float>();
vec.z = cursor.at(displayName).at("z").get<float>();
dataMember.set(metaAny, vec);
}
else if (fieldType == entt::resolve<Vector4>())
{
Vector4 vec;
vec.x = cursor.at(displayName).at("x").get<float>();
vec.y = cursor.at(displayName).at("y").get<float>();
vec.z = cursor.at(displayName).at("z").get<float>();
vec.w = cursor.at(displayName).at("w").get<float>();
dataMember.set(metaAny, vec);
}
else if (fieldType == entt::resolve<ResourceFile>())
{
std::string fileKey = "file" + displayName;
if (cursor.contains(fileKey))
{
//std::string relativePath = cursor.at(fileKey).get<std::string>();
//ResourceFile resource;
//resource.file = std::make_shared<File>(relativePath);
//dataMember.set(metaAny, resource);
}
}
else if (fieldType == entt::resolve<std::string>())
{
dataMember.set(metaAny, cursor.at(displayName).get<std::string>());
}
}
}
};
}

10
Test/.runsettings Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<Catch2Adapter>
<CombinedTimeout>30000</CombinedTimeout><!-- 30s in Milliseconds -->
<FilenameFilter>.*</FilenameFilter>
<DllRunnerCommandline>${catch2} ${dll}</DllRunnerCommandline>
</Catch2Adapter>
</RunSettings>

View File

@@ -0,0 +1,121 @@
#include "catch2/catch_amalgamated.hpp"
#include "Nuake/Scene/Components/Component.h"
#include "Nuake/Resource/Serializer/ComponentSerializer.h"
#include "entt/entt.hpp"
namespace Serialization
{
using namespace Nuake;
enum class TestEnum : int32_t
{
One,
Two,
Three,
Four
};
class TestData : public Component
{
NUAKECOMPONENT(TestData, "TestData");
public:
int myInt;
bool myBool;
std::string myString;
Vector2 myVec2;
Vector3 myVec3;
Vector4 myVec4;
TestEnum myEnum;
static void InitializeComponentClass()
{
BindComponentField<&TestData::myInt>("myInt", "myInt");
BindComponentField<&TestData::myBool>("myBool", "myBool");
BindComponentField<&TestData::myString>("myString", "myString");
BindComponentField<&TestData::myVec2>("myVec2", "myVec2");
BindComponentField<&TestData::myVec3>("myVec3", "myVec3");
BindComponentField<&TestData::myVec4>("myVec4", "myVec4");
BindComponentField<&TestData::myEnum>("myEnum", "myEnum");
}
};
TEST_CASE("Serialize Struct", "[Serialization]")
{
// Initialize component
TestData::InternalInitializeClass();
TestData testData =
{
.myInt = 1337,
.myBool = true,
.myString = "Hello World",
.myVec2 = Vector2(1, 2),
.myVec3 = Vector3(3, 4, 5),
.myVec4 = Vector4(6, 7, 8, 9),
.myEnum = TestEnum::Two
};
// Serialize into json
ComponentSerializer serializer;
json result = serializer.Serialize(testData);
// Test JSON result
REQUIRE(result.contains("TestData"));
REQUIRE(result["TestData"].contains("myInt"));
REQUIRE(result["TestData"]["myInt"] == testData.myInt);
REQUIRE(result["TestData"].contains("myBool"));
REQUIRE(result["TestData"]["myBool"] == testData.myBool);
REQUIRE(result["TestData"].contains("myString"));
REQUIRE(result["TestData"]["myString"] == testData.myString);
REQUIRE(result["TestData"].contains("myVec2"));
REQUIRE(result["TestData"]["myVec2"]["x"] == testData.myVec2.x);
REQUIRE(result["TestData"]["myVec2"]["y"] == testData.myVec2.y);
REQUIRE(result["TestData"].contains("myVec3"));
REQUIRE(result["TestData"]["myVec3"]["x"] == testData.myVec3.x);
REQUIRE(result["TestData"]["myVec3"]["y"] == testData.myVec3.y);
REQUIRE(result["TestData"]["myVec3"]["z"] == testData.myVec3.z);
REQUIRE(result["TestData"].contains("myVec4"));
REQUIRE(result["TestData"]["myVec4"]["x"] == testData.myVec4.x);
REQUIRE(result["TestData"]["myVec4"]["y"] == testData.myVec4.y);
REQUIRE(result["TestData"]["myVec4"]["z"] == testData.myVec4.z);
REQUIRE(result["TestData"]["myVec4"]["w"] == testData.myVec4.w);
}
TEST_CASE("Deserialize Struct", "[Serialization]")
{
// Initialize component
TestData::InternalInitializeClass();
TestData testData =
{
.myInt = 1337,
.myBool = true,
.myString = "Hello World",
.myVec2 = Vector2(1, 2),
.myVec3 = Vector3(3, 4, 5),
.myVec4 = Vector4(6, 7, 8, 9)
};
// Serialize into json
ComponentSerializer serializer;
json result = serializer.Serialize(testData);
// Deserialize
TestData inTestData = TestData{ };
serializer.Deserialize(result, inTestData);
// Test JSON result
REQUIRE(inTestData.myInt == testData.myInt);
REQUIRE(inTestData.myBool == testData.myBool);
REQUIRE(inTestData.myString == testData.myString);
REQUIRE(inTestData.myVec2 == testData.myVec2);
REQUIRE(inTestData.myVec3 == testData.myVec3);
REQUIRE(inTestData.myVec4 == testData.myVec4);
}
}

View File

@@ -0,0 +1,24 @@
#include "catch2/catch_amalgamated.hpp"
#define CATCH_CONFIG_MAIN
#include "Engine.h"
namespace Engine
{
TEST_CASE("Window creation", "[window]")
{
Nuake::Engine::Init();
REQUIRE(Nuake::Engine::GetCurrentWindow() != nullptr);
}
TEST_CASE("Window shutdown", "[window]")
{
Nuake::Engine::Init();
Nuake::Engine::GetCurrentWindow()->Close();
REQUIRE(Nuake::Engine::GetCurrentWindow()->ShouldClose());
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,76 @@
project "NuakeTest"
kind "ConsoleApp"
staticruntime "On"
language "C++"
cppdialect "C++20"
defines
{
table.unpack(globalDefines),
"_MBCS",
"IMGUI_DEFINE_MATH_OPERATORS",
"NK_VK",
"IMGUI_IMPL_VULKAN_NO_PROTOTYPES"
}
targetdir (binaryOutputDir)
objdir (intBinaryOutputDir)
debugdir (binaryOutputDir)
files
{
-- Main Sources
"Source/**.cpp",
"Source/**.h",
"Vendors/**.h",
"Vendors/**.cpp",
}
includedirs
{
".",
"Source",
"Vendors",
"../../Nuake/Source",
"../../Nuake/Vendors",
"../../Nuake/Thirdparty/entt/src"
}
links
{
"Nuake",
"glad",
"GLFW",
"assimp",
"JoltPhysics",
"soloud",
"Coral.Native",
"DebugUtils",
"Detour",
"DetourCrowd",
"DetourTileCache",
"Recast",
"tracy",
"yoga",
"msdf-gen",
"msdf-atlas-gen",
"Freetype",
"vma"
}
filter { "system:windows", "action:vs*"}
flags
{
"MultiProcessorCompile",
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
buildoptions { "/Zi" }
filter "configurations:Release"
runtime "Release"
optimize "on"

1
Test/premake5.lua Normal file
View File

@@ -0,0 +1 @@
include "NuakeTest/premake5.lua"

71
bindings.json Normal file
View File

@@ -0,0 +1,71 @@
{
"Modules": [
{
"Functions": [
{
"Args": [
{
"Name": "volume",
"Type": "float"
}
],
"Name": "SetVolume",
"NumArgs": 1,
"ReturnType": "void"
},
{
"Args": [
{
"Name": "muted",
"Type": "bool"
}
],
"Name": "SetMuted",
"NumArgs": 1,
"ReturnType": "void"
},
{
"Name": "HelloWorld",
"NumArgs": 0,
"ReturnType": "void"
},
{
"Args": [
{
"Name": "name",
"Type": "string"
}
],
"Name": "SetName",
"NumArgs": 1,
"ReturnType": "void"
}
],
"Name": "AudioModule"
},
{
"Functions": [
{
"Name": "ExampleFunction",
"NumArgs": 0,
"ReturnType": "void"
},
{
"Args": [
{
"Name": "hi2",
"Type": "string"
}
],
"Name": "ExampleModuleLog16",
"NumArgs": 1,
"ReturnType": "void"
}
],
"Name": "ExampleModule"
},
{
"Name": "FidelityFXModule"
}
]
}

View File

@@ -84,3 +84,4 @@ include "Runtime/premake5.lua"
include "NuakeNet/premake5.lua"
include "NuakeNetGenerator/premake5.lua"
include "EditorNet/premake5.lua"
include "Test/premake5.lua"