Started shading pass

This commit is contained in:
antopilo
2025-01-09 19:08:04 -05:00
parent e5671fd47b
commit a197ab62a6
19 changed files with 322 additions and 179 deletions

View File

@@ -1,5 +1,6 @@
#pragma once
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_FORCE_ROW_MAJOR
#include <glm/ext/vector_float4.hpp>
#include <glm/ext/vector_float3.hpp>

View File

@@ -29,8 +29,8 @@ namespace Nuake
public:
float Near = 400.0f;
float Far = 0.001f;
float Near = 200.0f;
float Far = 0.01f;
float AspectRatio = 16.0f / 9.0f;
Vector3 Direction = Vector3(0, 0, 1);

View File

@@ -42,7 +42,7 @@ namespace Nuake {
inline Matrix4 GetCascadeViewProjection(const int i) { return m_CascadeViewProjections[i]; }
private:
static const int CSM_SPLIT_AMOUNT = 4;
const float CSM_NEAR_CLIP = 0.001f;
const float CSM_NEAR_CLIP = 0.1f;
const float CSM_FAR_CLIP = 400.0f;
const float CSM_CLIP_RANGE = CSM_FAR_CLIP - CSM_NEAR_CLIP;

View File

@@ -10,7 +10,6 @@ void DescriptorLayoutBuilder::AddBinding(uint32_t binding, VkDescriptorType type
newbind.binding = binding;
newbind.descriptorCount = count;
newbind.descriptorType = type;
Bindings.push_back(newbind);
}
@@ -31,6 +30,7 @@ VkDescriptorSetLayout DescriptorLayoutBuilder::Build(VkDevice device, VkShaderSt
info.pBindings = Bindings.data();
info.bindingCount = (uint32_t)Bindings.size();
info.flags = flags;
VkDescriptorSetLayout set;
VK_CALL(vkCreateDescriptorSetLayout(device, &info, nullptr, &set));

View File

@@ -43,6 +43,8 @@ void RenderPass::ClearAttachments(PassRenderContext& ctx)
auto& gpuResources = GPUResources::Get();
gpuResources.AddTexture(newAttachment);
VulkanUtil::TransitionImage(ctx.commandBuffer, newAttachment->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
// TODO: Queue deletion of old textures
}
@@ -53,6 +55,8 @@ void RenderPass::ClearAttachments(PassRenderContext& ctx)
auto& gpuResources = GPUResources::Get();
gpuResources.AddTexture(newDepthAttachment);
VulkanUtil::TransitionImage(ctx.commandBuffer, newDepthAttachment->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, true);
}
// Clear all color attachments
@@ -114,17 +118,19 @@ void RenderPass::Render(PassRenderContext& ctx)
VkRenderingAttachmentInfo attachmentInfo = VulkanInit::AttachmentInfo(attachment.Image->GetImageView(), nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
renderAttachmentInfos.push_back(attachmentInfo);
}
VkRenderingAttachmentInfo depthAttachmentInfo = {};
if (DepthAttachment.Image)
{
depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(DepthAttachment.Image->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
}
}
VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, !DepthAttachment.Image ? nullptr : &depthAttachmentInfo);
renderInfo.colorAttachmentCount = std::size(renderAttachmentInfos);
renderInfo.pColorAttachments = renderAttachmentInfos.data();
// Begin render!
vkCmdBeginRendering(ctx.commandBuffer, &renderInfo);
{
@@ -243,7 +249,6 @@ void RenderPass::Build()
bufferRange.offset = 0;
bufferRange.size = PushConstantSize;
bufferRange.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
pushRange = 1;
}
@@ -280,8 +285,12 @@ void RenderPass::Build()
}
// Set depth attachment, for now we assume every pass has a depth attachment
pipelineBuilder.SetDepthFormat(static_cast<VkFormat>(DepthAttachment.Format));
pipelineBuilder.EnableDepthTest(true, VK_COMPARE_OP_GREATER_OR_EQUAL);
if (HasDepthTest)
{
pipelineBuilder.SetDepthFormat(static_cast<VkFormat>(DepthAttachment.Format));
pipelineBuilder.EnableDepthTest(true, VK_COMPARE_OP_GREATER_OR_EQUAL);
}
Pipeline = pipelineBuilder.BuildPipeline(VkRenderer::Get().GetDevice());
}
@@ -372,67 +381,66 @@ void RenderPipeline::Execute(PassRenderContext& ctx)
return;
}
std::vector<TextureAttachment> transitionedInputs;
for (auto& pass : RenderPasses)
{
for (auto& input : pass.GetInputAttachments())
{
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
// Handle old and new layouts based on attachment type
barrier.oldLayout = input.Format != ImageFormat::D32F ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
// Access masks for color or depth-stencil attachments
if (input.Format != ImageFormat::D32F) {
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
else {
barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
// Include stencil aspect if applicable
//if (input.HasStencilComponent()) {
// barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
//}
}
// Destination access mask is always for shaders reading
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
// No queue family ownership transfer in this case
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
// Set the image and subresource range
barrier.image = input.Image->GetImage();
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
// Choose appropriate source pipeline stage for color or depth-stencil
VkPipelineStageFlags srcStage = (input.Format != ImageFormat::D32F)
? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
: (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
// Insert the pipeline barrier
vkCmdPipelineBarrier(
ctx.commandBuffer,
srcStage, // Source stage
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // Destination stage
0,
0, nullptr,
0, nullptr,
1, &barrier
);
//for (auto& input : pass.GetInputAttachments())
//{
// VkImageMemoryBarrier barrier{};
// barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
//
// // Handle old and new layouts based on attachment type
// barrier.oldLayout = input.Format != ImageFormat::D32F ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
// barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
//
// // Access masks for color or depth-stencil attachments
// if (input.Format != ImageFormat::D32F) {
// barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
// barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
// }
// else {
// barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
// barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
//
// // Include stencil aspect if applicable
// //if (input.HasStencilComponent()) {
// // barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
// //}
// }
//
// // Destination access mask is always for shaders reading
// barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
//
// // No queue family ownership transfer in this case
// barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
// barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
//
// // Set the image and subresource range
// barrier.image = input.Image->GetImage();
// barrier.subresourceRange.baseMipLevel = 0;
// barrier.subresourceRange.levelCount = 1;
// barrier.subresourceRange.baseArrayLayer = 0;
// barrier.subresourceRange.layerCount = 1;
//
// // Choose appropriate source pipeline stage for color or depth-stencil
// VkPipelineStageFlags srcStage = (input.Format != ImageFormat::D32F)
// ? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
// : (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
//
// // Insert the pipeline barrier
// vkCmdPipelineBarrier(
// ctx.commandBuffer,
// srcStage, // Source stage
// VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // Destination stage
// 0,
// 0, nullptr,
// 0, nullptr,
// 1, &barrier
// );
transitionedInputs.push_back(input);
}
// transitionedInputs.push_back(input);
//}
pass.ClearAttachments(ctx);
pass.TransitionAttachments(ctx);
@@ -443,6 +451,7 @@ void RenderPipeline::Execute(PassRenderContext& ctx)
}
for (auto& transitionedOutputs : transitionedInputs)
{
if (transitionedOutputs.Format == ImageFormat::D32F)
@@ -454,5 +463,6 @@ void RenderPipeline::Execute(PassRenderContext& ctx)
VulkanUtil::TransitionImage(ctx.commandBuffer, transitionedOutputs.Image->GetImage(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
}
}
}

View File

@@ -46,6 +46,7 @@ namespace Nuake
{
private:
std::string Name;
bool HasDepthTest = true;
Ref<VulkanShader> VertShader;
Ref<VulkanShader> FragShader;
@@ -77,6 +78,7 @@ namespace Nuake
void Render(PassRenderContext& ctx);
public:
void SetDepthTest(bool enabled) { HasDepthTest = enabled; }
std::string GetName() const { return Name; }
TextureAttachment& AddAttachment(const std::string& name, ImageFormat format, ImageUsage usage = ImageUsage::Default);
TextureAttachment& GetAttachment(const std::string& name);

View File

@@ -211,18 +211,15 @@ void PipelineBuilder::EnableBlendingAdditive()
void PipelineBuilder::EnableBlendingAlphaBlend(size_t count)
{
for (size_t i = 0; i < count; i++)
{
VkPipelineColorBlendAttachmentState colorBlend = {};
colorBlend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlend.blendEnable = VK_TRUE;
colorBlend.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlend.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlend.colorBlendOp = VK_BLEND_OP_ADD;
colorBlend.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlend.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlend.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendAttachmentState colorBlend = {};
colorBlend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlend.blendEnable = VK_TRUE;
colorBlend.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlend.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlend.colorBlendOp = VK_BLEND_OP_ADD;
colorBlend.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlend.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlend.alphaBlendOp = VK_BLEND_OP_ADD;
ColorBlendAttachment.push_back(colorBlend);
}
ColorBlendAttachment.push_back(colorBlend);
}

View File

@@ -12,12 +12,12 @@ namespace Nuake
VkPipelineInputAssemblyStateCreateInfo InputAssembly;
VkPipelineRasterizationStateCreateInfo Rasterizer;
std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachment;
std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachment = std::vector<VkPipelineColorBlendAttachmentState>();
VkPipelineMultisampleStateCreateInfo Multisampling;
VkPipelineLayout PipelineLayout;
VkPipelineDepthStencilStateCreateInfo DepthStencil;
VkPipelineRenderingCreateInfo RenderInfo;
std::vector<VkFormat> ColorAttachmentformats;
std::vector<VkFormat> ColorAttachmentformats = std::vector<VkFormat>();
PipelineBuilder() { Clear(); }

View File

@@ -235,7 +235,7 @@ VkPipelineShaderStageCreateInfo VulkanInit::PipelineShaderStageCreateInfo(VkShad
}
// This is a helper to transtion images between readable, writable layouts.
void VulkanUtil::TransitionImage(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout)
void VulkanUtil::TransitionImage(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout, bool isDepth)
{
VkImageMemoryBarrier2 imageBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
imageBarrier.pNext = nullptr;
@@ -247,7 +247,7 @@ void VulkanUtil::TransitionImage(VkCommandBuffer cmd, VkImage image, VkImageLayo
imageBarrier.oldLayout = currentLayout;
imageBarrier.newLayout = newLayout;
VkImageAspectFlags aspectMask = (newLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
VkImageAspectFlags aspectMask = (newLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL || isDepth) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
imageBarrier.subresourceRange = VulkanInit::ImageSubResourceRange(aspectMask);
imageBarrier.image = image;

View File

@@ -44,7 +44,7 @@ namespace Nuake
VulkanUtil() = delete;
~VulkanUtil() = delete;
static void TransitionImage(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout);
static void TransitionImage(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout, bool isDepth = false);
static void CopyImageToImage(VkCommandBuffer cmd, VkImage source, VkImage destination, Vector2 srcSize, Vector2 dstSize);
};
}

View File

@@ -136,8 +136,8 @@ void VkRenderer::Initialize()
InitDescriptors();
InitPipeline();
InitTrianglePipeline();
//InitPipeline();
//InitTrianglePipeline();
InitImgui();
@@ -204,13 +204,14 @@ void VkRenderer::SelectGPU()
VkPhysicalDeviceVulkan13Features features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES };
features.dynamicRendering = true;
features.synchronization2 = true;
VkPhysicalDeviceVulkan12Features features12{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES };
features12.bufferDeviceAddress = true;
features12.descriptorIndexing = true;
features12.runtimeDescriptorArray = true;
std::vector<const char*> requiredExtensions = { VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME };
vkb::PhysicalDeviceSelector selector{ VkbInstance };
vkb::PhysicalDevice physicalDevice = selector
.set_minimum_version(1, 3)
@@ -359,7 +360,7 @@ void VkRenderer::InitDescriptors()
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
CameraBufferDescriptorLayout = builder.Build(Device, VK_SHADER_STAGE_VERTEX_BIT);
CameraBufferDescriptorLayout = builder.Build(Device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
// Triangle vertex buffer layout
@@ -727,7 +728,9 @@ void VkRenderer::InitImgui()
void VkRenderer::BeginScene(const Matrix4& view, const Matrix4& projection)
{
CameraData newData = { view, projection };
Matrix4 proj = projection;
//proj[1][1] *= -1.0f;
CameraData newData = { view, projection, glm::inverse(view), glm::inverse(proj)};
//UploadCameraData(newData);
SceneRenderer->UpdateCameraData(newData);
}
@@ -769,8 +772,8 @@ bool VkRenderer::Draw()
VulkanUtil::TransitionImage(cmd, DrawImage->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
// Execute compute shader that writes to the image
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, Pipeline);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, PipelineLayout, 0, 1, &DrawImageDescriptors, 0, nullptr);
//vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, Pipeline);
//vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, PipelineLayout, 0, 1, &DrawImageDescriptors, 0, nullptr);
VulkanUtil::TransitionImage(cmd, DrawImage->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
//vkCmdDispatch(cmd, std::ceil(DrawExtent.width / 16.0), std::ceil(DrawExtent.height / 16.0), 1);

View File

@@ -119,6 +119,8 @@ namespace Nuake
{
Matrix4 View;
Matrix4 Projection;
Matrix4 InvView;
Matrix4 InvProjection;
};
// Renderer configuration
@@ -257,7 +259,7 @@ namespace Nuake
void ImmediateSubmit(std::function<void(VkCommandBuffer cmd)>&& function);
void UploadCameraData(const CameraData& data);
auto& GetRenderPipeline() { return this->SceneRenderer->GetRenderPipeline(); }
VkDescriptorSet GetViewportDescriptor() const { return DrawImageDescriptors; }
Ref<VulkanImage> GetDrawImage() const { return DrawImage; }
};

View File

@@ -128,7 +128,7 @@ void GPUResources::CreateBindlessLayout()
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
CameraDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_VERTEX_BIT);
CameraDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
{
@@ -216,7 +216,12 @@ std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
return layouts;
}
uint32_t GPUResources::GetBindlessTextureID(const UUID & id)
uint32_t GPUResources::GetBindlessTextureID(const UUID& id)
{
return 0;
if (BindlessTextureMapping.find(id) == BindlessTextureMapping.end())
{
return 0;
}
return BindlessTextureMapping[id];
}

View File

@@ -44,14 +44,16 @@ void VkSceneRenderer::Init()
MeshMaterialMapping.clear();
std::vector<Vertex> quadVertices = {
{{-1.0f, -1.0f, 0.0f }, 0.0f, {}, 0.0f },
{{ 1.0f, -1.0f, 0.0f }, 1.0f, {}, 0.0f },
{{ 1.0f, 1.0f, 0.0f }, 1.0f, {}, 1.0f },
{{-1.0f, 1.0f, 0.0f }, 0.0f, {}, 1.0f }
{ Vector3(-1.0f, 1.0f, 1.0f), 0.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
{ Vector3(1.0f, 1.0f, 1.0f), 1.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
{ Vector3(-1.0f, -1.0f, 1.0f), 0.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
{ Vector3(1.0f, -1.0f, 1.0f), 1.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
{ Vector3(-1.0f, -1.0f, 1.0f), 0.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
{ Vector3(1.0f, 1.0f, 1.0f), 1.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) }
};
std::vector<uint32_t> quadIndices = {
0, 1, 2, 2, 3, 0
5, 4, 3, 2, 1, 0
};
quadMesh = CreateRef<VkMesh>(quadVertices, quadIndices);
@@ -87,6 +89,7 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
GBufferPipeline.Execute(passCtx);
}
ModelPushConstant modelPushConstant{};
ShadingPushConstant shadingPushConstant;
void VkSceneRenderer::EndScene()
{
@@ -94,10 +97,13 @@ void VkSceneRenderer::EndScene()
auto& cmd = Context.CommandBuffer;
auto& albedo = GBufferPipeline.GetRenderPass("GBuffer").GetAttachment("Albedo");
auto& normal = GBufferPipeline.GetRenderPass("GBuffer").GetAttachment("Normal");
VulkanUtil::TransitionImage(cmd, albedo.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
VulkanUtil::TransitionImage(cmd, normal.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
VulkanUtil::TransitionImage(cmd, vk.DrawImage->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VulkanUtil::CopyImageToImage(cmd, albedo.Image->GetImage(), vk.GetDrawImage()->GetImage(), albedo.Image->GetSize(), vk.DrawImage->GetSize());
VulkanUtil::CopyImageToImage(cmd, normal.Image->GetImage(), vk.GetDrawImage()->GetImage(), albedo.Image->GetSize(), vk.DrawImage->GetSize());
VulkanUtil::TransitionImage(cmd, vk.DrawImage->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
VulkanUtil::TransitionImage(cmd, normal.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
VulkanUtil::TransitionImage(cmd, albedo.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
}
@@ -106,6 +112,8 @@ void VkSceneRenderer::CreateBuffers()
CameraData camData{};
camData.View = Matrix4(1.0f);
camData.Projection = Matrix4(1.0f);
camData.InvView = Matrix4(1.0f);
camData.InvProjection = Matrix4(1.0f);
// init camera buffer
GPUResources& resources = GPUResources::Get();
@@ -149,7 +157,7 @@ void VkSceneRenderer::CreateDescriptors()
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
CameraBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_VERTEX_BIT);
CameraBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
}
{
@@ -241,7 +249,6 @@ void VkSceneRenderer::CreateDescriptors()
void VkSceneRenderer::CreatePipelines()
{
GBufferPipeline = RenderPipeline();
auto& gBufferPass = GBufferPipeline.AddPass("GBuffer");
gBufferPass.SetShaders(Shaders["basic_vert"], Shaders["basic_frag"]);
gBufferPass.AddAttachment("Albedo", ImageFormat::RGBA8);
@@ -249,7 +256,6 @@ void VkSceneRenderer::CreatePipelines()
gBufferPass.AddAttachment("Material", ImageFormat::RGBA8);
gBufferPass.AddAttachment("Depth", ImageFormat::D32F, ImageUsage::Depth);
gBufferPass.SetPushConstant<ModelPushConstant>(modelPushConstant);
gBufferPass.SetPreRender([&](PassRenderContext& ctx) {
std::vector<VkDescriptorSet> descriptors2 = { CameraBufferDescriptors, ModelBufferDescriptor };
vkCmdBindDescriptorSets(
@@ -287,9 +293,7 @@ void VkSceneRenderer::CreatePipelines()
);
vkCmdBindDescriptorSets(ctx.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx.renderPass->PipelineLayout, 3, 1, &SamplerDescriptor, 0, nullptr);
});
gBufferPass.SetRender([&](PassRenderContext& ctx){
auto& cmd = ctx.commandBuffer;
auto& scene = ctx.scene;
@@ -349,14 +353,16 @@ void VkSceneRenderer::CreatePipelines()
});
/*
auto& shadingPass = GBufferPipeline.AddPass("Shading");
shadingPass.SetShaders(Shaders["shading_vert"], Shaders["shading_frag"]);
shadingPass.SetPushConstant<ModelPushConstant>(modelPushConstant);
shadingPass.AddAttachment("Output", ImageFormat::RGBA16F);
shadingPass.AddAttachment("DepthShading", ImageFormat::D32F, ImageUsage::Depth);
shadingPass.AddInput("Albedo"); // We need to sync those
shadingPass.SetPushConstant<ShadingPushConstant>(shadingPushConstant);
shadingPass.AddAttachment("Output", ImageFormat::RGBA8);
shadingPass.SetDepthTest(false);
shadingPass.AddInput("Albedo");
shadingPass.AddInput("Normal");
//shadingPass.AddInput("Depth");
shadingPass.AddInput("Material");
shadingPass.SetPreRender([&](PassRenderContext& ctx) {
std::vector<VkDescriptorSet> descriptors2 = { CameraBufferDescriptors, ModelBufferDescriptor };
vkCmdBindDescriptorSets(
@@ -395,19 +401,22 @@ void VkSceneRenderer::CreatePipelines()
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());
});
shadingPass.SetRender([](PassRenderContext& ctx) {
modelPushConstant.Index = 0;
modelPushConstant.MaterialIndex = 0;
vkCmdPushConstants(
ctx.commandBuffer,
ctx.renderPass->PipelineLayout,
VK_SHADER_STAGE_ALL_GRAPHICS, // Stage matching the pipeline layout
0, // Offset
sizeof(ModelPushConstant), // Size of the push constant
&modelPushConstant // Pointer to the value
sizeof(ShadingPushConstant), // Size of the push constant
&shadingPushConstant // Pointer to the value
);
auto descSet = quadMesh->GetDescriptorSet();
@@ -425,7 +434,7 @@ void VkSceneRenderer::CreatePipelines()
vkCmdBindIndexBuffer(ctx.commandBuffer, quadMesh->GetIndexBuffer()->GetBuffer(), 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(ctx.commandBuffer, quadMesh->GetIndexBuffer()->GetSize() / sizeof(uint32_t), 1, 0, 0, 0);
});
*/
GBufferPipeline.Build();
}
@@ -439,7 +448,8 @@ void VkSceneRenderer::UpdateCameraData(const CameraData& data)
CameraData adjustedData = data;
adjustedData.View = data.View;
adjustedData.Projection = data.Projection;
adjustedData.InvView = data.InvView;
adjustedData.InvProjection = data.InvProjection;
void* mappedData;
vmaMapMemory(VulkanAllocator::Get().GetAllocator(), (VkRenderer::Get().GetCurrentFrame().CameraStagingBuffer->GetAllocation()), &mappedData);
memcpy(mappedData, &adjustedData, sizeof(CameraData));

View File

@@ -25,6 +25,14 @@ namespace Nuake
char padding[120]; // 124 bytes to reach 128 bytes
};
struct ShadingPushConstant
{
int AlbedoTextureID;
int DepthTextureID;
int NormalTextureID;
int MaterialTextureID;
};
struct ModelData
{
std::array<Matrix4, 3000> Data;
@@ -111,6 +119,8 @@ namespace Nuake
void BeginScene(RenderContext inContext);
void EndScene();
RenderPipeline& GetRenderPipeline() { return GBufferPipeline; }
private:
void LoadShaders();
void CreateBuffers();

View File

@@ -1,3 +1,13 @@
struct Camera
{
float4x4 view;
float4x4 proj;
float4x4 invView;
float4x4 invProj;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
[[vk::binding(0, 3)]]
SamplerState mySampler : register(s0); // Sampler binding at slot s0
@@ -20,29 +30,149 @@ StructuredBuffer<Material> material;
Texture2D textures[]; // Array de 500 textures
struct PSInput {
float4 Position : SV_Position;
float2 UV : TEXCOORD0;
float4x4 InvProj : TEXCOORD1;
float4x4 InvView : TEXCOORD2;
};
struct PSOutput {
float4 oColor0 : SV_TARGET;
};
struct ModelPushConstant
struct ShadingPushConstant
{
int modelIndex; // Push constant data
int materialIndex;
int AlbedoInputTextureId;
int DepthInputTextureId;
int NormalInputTextureId;
int MaterialInputTextureId;
};
[[vk::push_constant]]
ModelPushConstant pushConstants;
ShadingPushConstant pushConstants;
float3 WorldPosFromDepth(float depth, float2 uv, float4x4 invProj, float4x4 invView)
{
float z = depth;
float4 clipSpacePosition = float4(uv.x * 2.0 - 1.0, (uv.y * 2.0 - 1.0), z, 1.0f);
float4 viewSpacePosition = mul(invProj, clipSpacePosition);
viewSpacePosition /= viewSpacePosition.w;
float4 worldSpacePosition = mul(invView, viewSpacePosition);
return worldSpacePosition.xyz;
}
float LinearizeDepth(float depth, float nearPlane, float farPlane, bool reverseDepth)
{
if (reverseDepth)
{
// Reverse depth (near plane = 1.0, far plane = 0.0)
return nearPlane * farPlane / lerp(farPlane, nearPlane, depth);
}
else
{
// Standard depth (near plane = 0.0, far plane = 1.0)
return (2.0 * nearPlane * farPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));
}
}
const float PI = 3.141592653589793f;
float DistributionGGX(float3 N, float3 H, float a)
{
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH * NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
float GeometrySchlickGGX(float NdotV, float k)
{
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float GeometrySmith(float3 N, float3 V, float3 L, float k)
{
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx1 = GeometrySchlickGGX(NdotV, k);
float ggx2 = GeometrySchlickGGX(NdotL, k);
return ggx1 * ggx2;
}
float3 fresnelSchlick(float cosTheta, float3 F0)
{
return F0 + (1.0 - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);
}
float3 fresnelSchlickRoughness(float cosTheta, float3 F0, float roughness)
{
float roughnessTerm = 1.0f - roughness;
return F0 + (max(float3(roughnessTerm, roughnessTerm, roughnessTerm), F0) - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);
}
PSOutput main(PSInput input)
{
PSOutput output;
Camera camData = camera[0];
int depthTexture = pushConstants.DepthInputTextureId;
float depth = textures[depthTexture].Sample(mySampler, input.UV).r;
output.oColor0 = float4(1, 0, 0, 1);
float3 worldPosition = WorldPosFromDepth(depth, input.UV, camData.invProj, camData.invView);
int albedoTextureId = pushConstants.AlbedoInputTextureId;
float3 albedo = textures[albedoTextureId].Sample(mySampler, input.UV).xyz;
float3 normal = textures[pushConstants.NormalInputTextureId].Sample(mySampler, input.UV).rgb;
output.oColor0 = float4(normal, 1);
return output;
float4 materialSample = textures[pushConstants.MaterialInputTextureId].Sample(mySampler, input.UV);
float metallic = materialSample.r;
float ao = materialSample.g;
float roughness = materialSample.b;
float3 eyePosition = camData.view[3].xyz;
float3 N = normal;
float3 V = normalize(eyePosition - worldPosition);
float3 R = reflect(-V, N);
float3 F0 = float3(0.04, 0.04, 0.04);
F0 = lerp(F0, albedo, metallic);
float3 Lo = float3(0.0, 0.0, 0.0);
// Directional light
float3 dir = normalize(float3(0.1, -1.0, 0.1f));
float attenuation = 1.0f;
float3 L = dir;
float3 radiance = float3(1, 1, 1) * attenuation;
float3 H = normalize(V + L);
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
float3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
float3 nominator = NDF * G * F;
float denominator = 4 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; // 0.001 to prevent divide by zero.
float3 specular = nominator / denominator;
float3 kS = F;
float3 kD = float3(1.0, 1.0, 1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
Lo += (kD * albedo / PI + specular) * radiance * NdotL;
float3 ambient = (albedo) * ao * 0.5f;
float3 color = (ambient) + Lo;
output.oColor0 = float4(ambient, 1);
return output;
}

View File

@@ -2,6 +2,8 @@ struct Camera
{
float4x4 view;
float4x4 proj;
float4x4 invView;
float4x4 invProj;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
@@ -26,73 +28,32 @@ struct Vertex
[[vk::binding(0, 2)]]
StructuredBuffer<Vertex> vertexBuffer : register(t2);
struct ModelPushConstant
struct ShadingPushConstant
{
int modelIndex; // Push constant data
int materialIndex;
int AlbedoInputTextureId;
int DepthInputTextureId;
int NormalInputTextureId;
int MaterialInputTextureId;
};
[[vk::push_constant]]
ModelPushConstant pushConstants;
ShadingPushConstant pushConstants;
// Outputs
struct VSOutput {
float4 Position : SV_Position;
float2 UV : TEXCOORD0;
float4x4 InvProj : TEXCOORD1;
float4x4 InvView : TEXCOORD2;
};
float4x4 inverse(float4x4 m) {
float n11 = m[0][0], n12 = m[1][0], n13 = m[2][0], n14 = m[3][0];
float n21 = m[0][1], n22 = m[1][1], n23 = m[2][1], n24 = m[3][1];
float n31 = m[0][2], n32 = m[1][2], n33 = m[2][2], n34 = m[3][2];
float n41 = m[0][3], n42 = m[1][3], n43 = m[2][3], n44 = m[3][3];
float t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44;
float t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44;
float t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44;
float t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
float det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
float idet = 1.0f / det;
float4x4 ret;
ret[0][0] = t11 * idet;
ret[0][1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * idet;
ret[0][2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * idet;
ret[0][3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * idet;
ret[1][0] = t12 * idet;
ret[1][1] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * idet;
ret[1][2] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * idet;
ret[1][3] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * idet;
ret[2][0] = t13 * idet;
ret[2][1] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * idet;
ret[2][2] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * idet;
ret[2][3] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * idet;
ret[3][0] = t14 * idet;
ret[3][1] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * idet;
ret[3][2] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * idet;
ret[3][3] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * idet;
return ret;
}
// Main vertex shader
VSOutput main(uint vertexIndex : SV_VertexID)
{
VSOutput output;
Camera camData = camera[0];
output.InvProj = inverse(camData.proj);
output.InvView = inverse(camData.view);
Vertex v = vertexBuffer[vertexIndex];
output.UV = float2(v.uv_x, v.uv_y);
output.Position = float4(v.position, 1.0f);
return output;
}

View File

@@ -1,3 +1,13 @@
struct Camera
{
float4x4 view;
float4x4 proj;
float4x4 invView;
float4x4 invProj;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
[[vk::binding(0, 3)]]
SamplerState mySampler : register(s0); // Sampler binding at slot s0
@@ -63,7 +73,7 @@ PSOutput main(PSInput input)
normal = mul(input.TBN, normal);
normal = normal / 2.0f + 0.5f;
output.oNormal = float4(normal, 1.0f);
output.oNormal = float4(float3(1, 0, 0), 1.0f);
// MATERIAL
@@ -82,7 +92,7 @@ PSOutput main(PSInput input)
albedoColor.xyz = albedoSample.xyz;
}
output.oColor0 = albedoColor;
output.oColor0 = float4(normal, 1.0);
// MATERIAL PROPERTIES
float metalnessValue = inMaterial.metalnessValue;
if(inMaterial.hasMetalness == 1)

View File

@@ -2,6 +2,8 @@ struct Camera
{
float4x4 view;
float4x4 proj;
float4x4 invView;
float4x4 invProj;
};
[[vk::binding(0, 0)]]
StructuredBuffer<Camera> camera : register(t0);
@@ -65,6 +67,6 @@ VSOutput main(uint vertexIndex : SV_VertexID)
float3 T = normalize(mul((float3x3)modelData.model, normalize(v.tangent.xyz)));
float3 B = normalize(mul((float3x3)modelData.model, normalize(v.bitangent.xyz)));
float3 N = normalize(mul((float3x3)modelData.model, normalize(v.normal)).xyz);
output.TBN = transpose(float3x3(T, B, N));
output.TBN = float3x3(T, B, N);
return output;
}