Bindless Camera views

This commit is contained in:
antopilo
2025-01-10 21:12:59 -05:00
parent da6b23cb07
commit d419d6019f
14 changed files with 217 additions and 17 deletions

View File

@@ -21,6 +21,7 @@ namespace Nuake
VkCommandBuffer commandBuffer;
Vector2 resolution;
RenderPass* renderPass = nullptr;
UUID cameraID;
};
class TextureAttachment

View File

@@ -1,5 +1,6 @@
#pragma once
#include "src/Core/Core.h"
#include "src/Resource/UUID.h"
#include <volk/volk.h>
@@ -12,6 +13,7 @@ namespace Nuake
Ref<Scene> CurrentScene; // The scene we are rendering
VkCommandBuffer CommandBuffer; // The command buffer we are recording into
Vector2 Size;
UUID CameraID;
// ...
// We might add more to this!
};

View File

@@ -8,7 +8,7 @@
#include "src/Rendering/Vulkan/VulkanImage/VulkanImage.h"
#include "src/Rendering/Vulkan/VkMesh.h"
#include "src/Rendering/Textures/TextureManager.h"
#include "src/Rendering/Vulkan/VulkanAllocatedBuffer.h"
#include "src/Rendering/Vulkan/DescriptorLayoutBuilder.h"
#include "src/Rendering/Vulkan/VulkanRenderer.h"
@@ -61,13 +61,16 @@ namespace Nuake
VkDescriptorSet SamplerDescriptor;
VkDescriptorSet MaterialDescriptor;
VkDescriptorSet LightsDescriptor;
VkDescriptorSet CamerasDescriptor;
std::map<UUID, uint32_t> BindlessTextureMapping;
std::map<UUID, uint32_t> CameraMapping;
Ref<AllocatedBuffer> CamerasBuffer;
public:
VkDescriptorSet TextureDescriptor;
VkDescriptorSet CamerasDescriptor;
static GPUResources& Get()
{
static GPUResources instance;
@@ -101,6 +104,8 @@ namespace Nuake
std::vector<VkDescriptorSetLayout> GetBindlessLayout();
uint32_t GetBindlessTextureID(const UUID& id);
uint32_t GetBindlessCameraID(const UUID& id);
void RecreateBindlessTextures();
void RecreateBindlessCameras();
private:

View File

@@ -114,6 +114,7 @@ VulkanImage::VulkanImage(ImageFormat inFormat, Vector2 inSize, ImageUsage usage)
{
drawImageUsages |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
drawImageUsages |= VK_IMAGE_USAGE_SAMPLED_BIT;
drawImageUsages |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
}
VkImageCreateInfo imgCreateInfo = VulkanInit::ImageCreateInfo(static_cast<VkFormat>(inFormat), drawImageUsages, vkExtent);

View File

@@ -158,7 +158,6 @@ namespace Nuake
uint32_t FrameNumber = 0;
FrameData Frames[FRAME_OVERLAP];
VkQueue GPUQueue;
uint32_t GPUQueueFamily;
DeletionQueue MainDeletionQueue;
@@ -198,6 +197,7 @@ namespace Nuake
Ref<VkSceneRenderer> SceneRenderer;
public:
VkQueue GPUQueue;
Ref<VulkanImage> DrawImage;
Ref<VulkanImage> DepthImage;

View File

@@ -1,5 +1,7 @@
#include "VkResources.h"
#include "VulkanAllocator.h"
using namespace Nuake;
GPUResources::GPUResources()
@@ -10,7 +12,7 @@ GPUResources::GPUResources()
void GPUResources::Init()
{
CreateBindlessLayout();
CamerasBuffer = CreateBuffer(sizeof(MaterialBufferStruct) * MAX_MATERIAL, BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST, MemoryUsage::GPU_ONLY, "CamerasBuffer");
}
Ref<AllocatedBuffer> GPUResources::CreateBuffer(size_t size, BufferUsage flags, MemoryUsage usage, const std::string& name)
@@ -221,6 +223,9 @@ void GPUResources::CreateBindlessLayout()
void GPUResources::RecreateBindlessTextures()
{
// Ideally wed have update bit enabled ondescriptors
vkQueueWaitIdle(VkRenderer::Get().GPUQueue);
if (!TextureDescriptor)
{
CreateBindlessLayout();
@@ -254,6 +259,37 @@ void GPUResources::RecreateBindlessCameras()
CreateBindlessLayout();
}
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().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);
});
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);
}
std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
@@ -265,7 +301,8 @@ std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
SamplerDescriptorLayout,
MaterialDescriptorLayout,
TexturesDescriptorLayout,
LightsDescriptorLayout
LightsDescriptorLayout,
CamerasDescriptorLayout
};
return layouts;
}
@@ -279,3 +316,13 @@ uint32_t GPUResources::GetBindlessTextureID(const UUID& id)
return BindlessTextureMapping[id];
}
uint32_t GPUResources::GetBindlessCameraID(const UUID& id)
{
if (CameraMapping.find(id) == CameraMapping.end())
{
return 0;
}
return CameraMapping[id];
}

View File

@@ -64,6 +64,7 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
{
Context.CommandBuffer = inContext.CommandBuffer;
Context.CurrentScene = inContext.CurrentScene;
Context.CameraID = inContext.CameraID;
// Collect all global transform of things we will render
BuildMatrixBuffer();
@@ -85,6 +86,17 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
// Build camera view list
{
auto camera = scene->m_EditorCamera;
CameraView camData{};
camData.View = camera->GetTransform();
camData.Projection = camera->GetPerspective();
camData.InverseView = glm::inverse(camData.View);
camData.InverseProjection = glm::inverse(camData.Projection);
camData.Position = camera->GetTranslation();
camData.Near = camera->Near;
camData.Far = camera->Far;
GPUResources::Get().AddCamera(camera->ID, camData);
auto view = scene->m_Registry.view<TransformComponent, CameraComponent>();
for (auto e : view)
{
@@ -92,7 +104,7 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
CameraView camData{};
camData.View = camera.CameraInstance->GetTransform();
camData.Projection = camera.CameraInstance->GetPerspective();
camData.InverseView = glm::inverse(camData.Projection);
camData.InverseView = glm::inverse(camData.View);
camData.InverseProjection = glm::inverse(camData.Projection);
camData.Position = transform.GetGlobalTransform()[3];
camData.Near = camera.CameraInstance->Near;
@@ -105,17 +117,20 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
for (auto e : view)
{
auto [transform, light] = view.get<TransformComponent, LightComponent>(e);
light.CalculateViewProjection();
//light.CalculateViewProjection();
}
}
GPUResources::Get().RecreateBindlessCameras();
// Execute light
PassRenderContext passCtx = { };
passCtx.scene = inContext.CurrentScene;
passCtx.commandBuffer = inContext.CommandBuffer;
passCtx.resolution = Context.Size;
ShadowPipeline.Execute(passCtx);
passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(Context.CameraID);
//ShadowPipeline.Execute(passCtx);
GBufferPipeline.Execute(passCtx);
}
ModelPushConstant modelPushConstant{};
@@ -129,12 +144,15 @@ void VkSceneRenderer::EndScene()
auto& albedo = GBufferPipeline.GetRenderPass("GBuffer").GetAttachment("Albedo");
auto& normal = GBufferPipeline.GetRenderPass("GBuffer").GetAttachment("Normal");
auto& shading = GBufferPipeline.GetRenderPass("Shading").GetAttachment("Output");
auto& shadow = ShadowPipeline.GetRenderPass("Shadow").GetDepthAttachment();
auto& selectedOutput = shading;
selectedOutput.Image->TransitionLayout(cmd, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
vk.DrawImage->TransitionLayout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VulkanUtil::CopyImageToImage(cmd, selectedOutput.Image->GetImage(), vk.GetDrawImage()->GetImage(), selectedOutput.Image->GetSize(), vk.DrawImage->GetSize());
vk.DrawImage->TransitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL);
selectedOutput.Image->TransitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL);
GPUResources::Get().ClearCameras();
}
void VkSceneRenderer::CreateBuffers()
@@ -340,6 +358,17 @@ void VkSceneRenderer::CreatePipelines()
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(
ctx.commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
ctx.renderPass->PipelineLayout,
7, // firstSet
1, // descriptorSetCount
&GPUResources::Get().CamerasDescriptor, // pointer to the descriptor set(s)
0, // dynamicOffsetCount
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(ctx.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx.renderPass->PipelineLayout, 3, 1, &SamplerDescriptor, 0, nullptr);
});
shadowPass.SetRender([&](PassRenderContext& ctx) {
@@ -383,7 +412,7 @@ void VkSceneRenderer::CreatePipelines()
modelPushConstant.Index = ModelMatrixMapping[entity.GetID()];
modelPushConstant.MaterialIndex = MeshMaterialMapping[vkMesh->GetID()];
modelPushConstant.CameraID = ctx.cameraID;
vkCmdPushConstants(
cmd,
ctx.renderPass->PipelineLayout,
@@ -456,6 +485,17 @@ void VkSceneRenderer::CreatePipelines()
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(
ctx.commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
ctx.renderPass->PipelineLayout,
7, // firstSet
1, // descriptorSetCount
&GPUResources::Get().CamerasDescriptor, // pointer to the descriptor set(s)
0, // dynamicOffsetCount
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(ctx.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx.renderPass->PipelineLayout, 3, 1, &SamplerDescriptor, 0, nullptr);
});
gBufferPass.SetRender([&](PassRenderContext& ctx){
@@ -499,7 +539,7 @@ void VkSceneRenderer::CreatePipelines()
modelPushConstant.Index = ModelMatrixMapping[entity.GetID()];
modelPushConstant.MaterialIndex = MeshMaterialMapping[vkMesh->GetID()];
modelPushConstant.CameraID = ctx.cameraID;
vkCmdPushConstants(
cmd,
ctx.renderPass->PipelineLayout,
@@ -575,12 +615,24 @@ void VkSceneRenderer::CreatePipelines()
nullptr // dynamicOffsets
);
vkCmdBindDescriptorSets(
ctx.commandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
ctx.renderPass->PipelineLayout,
7, // firstSet
1, // descriptorSetCount
&GPUResources::Get().CamerasDescriptor, // pointer to the descriptor set(s)
0, // dynamicOffsetCount
nullptr // dynamicOffsets
);
auto& gpu = GPUResources::Get();
auto& gbufferPass = GBufferPipeline.GetRenderPass("GBuffer");
shadingPushConstant.AlbedoTextureID = gpu.GetBindlessTextureID(gbufferPass.GetAttachment("Albedo").Image->GetID());
shadingPushConstant.DepthTextureID = gpu.GetBindlessTextureID(gbufferPass.GetDepthAttachment().Image->GetID());
shadingPushConstant.NormalTextureID = gpu.GetBindlessTextureID(gbufferPass.GetAttachment("Normal").Image->GetID());
shadingPushConstant.MaterialTextureID = gpu.GetBindlessTextureID(gbufferPass.GetAttachment("Material").Image->GetID());
shadingPushConstant.CameraID = ctx.cameraID;
});
shadingPass.SetRender([](PassRenderContext& ctx) {
vkCmdPushConstants(
@@ -609,6 +661,7 @@ void VkSceneRenderer::CreatePipelines()
});
GBufferPipeline.Build();
ShadowPipeline.Build();
}
void VkSceneRenderer::SetGBufferSize(const Vector2& size)
@@ -616,7 +669,7 @@ void VkSceneRenderer::SetGBufferSize(const Vector2& size)
Context.Size = size;
}
void VkSceneRenderer::UpdateCameraData(const camera& data)
void VkSceneRenderer::UpdateCameraData(const CameraData& data)
{
CameraData adjustedData = data;
adjustedData.View = data.View;

View File

@@ -22,6 +22,7 @@ namespace Nuake
{
int Index;
int MaterialIndex;
int CameraID;
char padding[120]; // 124 bytes to reach 128 bytes
};
@@ -32,6 +33,7 @@ namespace Nuake
int NormalTextureID;
int MaterialTextureID;
int LightCount;
int CameraID;
};
struct ModelData

View File

@@ -46,6 +46,19 @@ struct Light
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct CameraView {
float4x4 View;
float4x4 Projection;
float4x4 ViewProjection;
float4x4 InverseView;
float4x4 InverseProjection;
float3 Position;
float Near;
float Far;
};
[[vk::binding(0, 7)]]
StructuredBuffer<CameraView> cameras;
struct PSInput {
float4 Position : SV_Position;
float2 UV : TEXCOORD0;
@@ -62,6 +75,7 @@ struct ShadingPushConstant
int NormalInputTextureId;
int MaterialInputTextureId;
int LightCount;
int CameraID;
};
[[vk::push_constant]]
@@ -139,10 +153,13 @@ PSOutput main(PSInput input)
{
PSOutput output;
Camera camData = camera[0];
CameraView camView = cameras[pushConstants.CameraID];
int depthTexture = pushConstants.DepthInputTextureId;
float depth = textures[depthTexture].Sample(mySampler, input.UV).r;
float3 worldPos = WorldPosFromDepth(depth, input.UV, camData.invProj, camData.invView);
float3 worldPos = WorldPosFromDepth(depth, input.UV, camView.InverseProjection, camView.InverseView);
int albedoTextureId = pushConstants.AlbedoInputTextureId;
float3 albedo = textures[albedoTextureId].Sample(mySampler, input.UV).xyz;
@@ -155,7 +172,7 @@ PSOutput main(PSInput input)
float roughness = materialSample.b;
float3 N = normal;
float3 V = normalize(camData.position - worldPos);
float3 V = normalize(camView.Position - worldPos);
float3 R = reflect(-V, N);
float3 F0 = float3(0.04, 0.04, 0.04);
F0 = lerp(F0, albedo, metallic);

View File

@@ -45,6 +45,19 @@ struct Light
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct CameraView {
float4x4 View;
float4x4 Projection;
float4x4 ViewProjection;
float4x4 InverseView;
float4x4 InverseProjection;
float3 Position;
float Near;
float Far;
};
[[vk::binding(0, 7)]]
StructuredBuffer<CameraView> cameras;
struct ShadingPushConstant
{
int AlbedoInputTextureId;
@@ -52,6 +65,7 @@ struct ShadingPushConstant
int NormalInputTextureId;
int MaterialInputTextureId;
int LightCount;
int CameraID;
};
[[vk::push_constant]]

View File

@@ -52,6 +52,19 @@ struct Light
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct CameraView {
float4x4 View;
float4x4 Projection;
float4x4 ViewProjection;
float4x4 InverseView;
float4x4 InverseProjection;
float3 Position;
float Near;
float Far;
};
[[vk::binding(0, 7)]]
StructuredBuffer<CameraView> cameras;
struct PSInput {
float4 Position : SV_Position;
};
@@ -64,6 +77,7 @@ struct ModelPushConstant
{
int modelIndex; // Push constant data
int materialIndex;
int cameraID;
};
[[vk::push_constant]]

View File

@@ -33,6 +33,7 @@ struct ModelPushConstant
{
int modelIndex; // Push constant data
int materialIndex;
int cameraID;
};
struct Light
@@ -51,6 +52,19 @@ struct Light
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct CameraView {
float4x4 View;
float4x4 Projection;
float4x4 ViewProjection;
float4x4 InverseView;
float4x4 InverseProjection;
float3 Position;
float Near;
float Far;
};
[[vk::binding(0, 7)]]
StructuredBuffer<CameraView> cameras;
[[vk::push_constant]]
ModelPushConstant pushConstants;
@@ -67,11 +81,13 @@ VSOutput main(uint vertexIndex : SV_VertexID)
Camera camData = camera[0];
ModelData modelData = model[pushConstants.modelIndex];
CameraView camView = cameras[pushConstants.cameraID];
// Load vertex data from the buffer
Vertex v = vertexBuffer[vertexIndex];
// Output the position of each vertex
output.Position = mul(camData.proj, mul(camData.view, mul(modelData.model, float4(v.position, 1.0f))));
output.Position = mul(camView.Projection, mul(camView.View, mul(modelData.model, float4(v.position, 1.0f))));
return output;
}

View File

@@ -52,6 +52,19 @@ struct Light
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct CameraView {
float4x4 View;
float4x4 Projection;
float4x4 ViewProjection;
float4x4 InverseView;
float4x4 InverseProjection;
float3 Position;
float Near;
float Far;
};
[[vk::binding(0, 7)]]
StructuredBuffer<CameraView> cameras;
struct PSInput {
float4 Position : SV_Position;
float3 Color : TEXCOORD0;
@@ -70,6 +83,7 @@ struct ModelPushConstant
{
int modelIndex; // Push constant data
int materialIndex;
int cameraID;
};
[[vk::push_constant]]

View File

@@ -33,6 +33,7 @@ struct ModelPushConstant
{
int modelIndex; // Push constant data
int materialIndex;
int cameraID;
};
struct Light
@@ -51,6 +52,19 @@ struct Light
[[vk::binding(0, 6)]]
StructuredBuffer<Light> lights;
struct CameraView {
float4x4 View;
float4x4 Projection;
float4x4 ViewProjection;
float4x4 InverseView;
float4x4 InverseProjection;
float3 Position;
float Near;
float Far;
};
[[vk::binding(0, 7)]]
StructuredBuffer<CameraView> cameras;
[[vk::push_constant]]
ModelPushConstant pushConstants;
@@ -69,14 +83,14 @@ VSOutput main(uint vertexIndex : SV_VertexID)
VSOutput output;
Camera camData = camera[0];
CameraView camView = cameras[pushConstants.cameraID];
ModelData modelData = model[pushConstants.modelIndex];
// Load vertex data from the buffer
Vertex v = vertexBuffer[vertexIndex];
// Output the position of each vertex
output.Position = mul(camData.proj, mul(camData.view, mul(modelData.model, float4(v.position, 1.0f))));
output.Position = mul(camView.Projection, mul(camView.View, mul(modelData.model, float4(v.position, 1.0f))));
output.Color = normalize(float3(v.position.xyz));
output.UV = float2(v.uv_x, v.uv_y);
output.Normal = normalize(v.normal);