Now renders albedo

This commit is contained in:
antopilo
2025-01-04 15:13:04 -05:00
parent 2d07e3777e
commit c67b9f18e5
12 changed files with 343 additions and 17 deletions

View File

@@ -203,7 +203,7 @@ namespace Nuake
if (v.contains("UV") && v["UV"].contains("x") && v["UV"].contains("y"))
{
vertex.uv_x = v["UV"]["x"];
vertex.uv_y = v["UV"]["x"];
vertex.uv_y = v["UV"]["y"];
}
}
catch (std::exception& /*e*/) {

View File

@@ -0,0 +1,155 @@
#include "DescriptorAllocatorGrowable.h"
#include "VulkanCheck.h"
using namespace Nuake;
VkDescriptorPool DescriptorAllocatorGrowable::GetPool(VkDevice device)
{
VkDescriptorPool newPool;
if (ReadyPools.size() != 0) {
newPool = ReadyPools.back();
ReadyPools.pop_back();
}
else {
//need to create a new pool
newPool = CreatePool(device, SetsPerPool, Ratios);
SetsPerPool = SetsPerPool * 1.5;
if (SetsPerPool > 4092) {
SetsPerPool = 4092;
}
}
return newPool;
}
VkDescriptorPool DescriptorAllocatorGrowable::CreatePool(VkDevice device, uint32_t setCount, std::span<PoolSizeRatio> poolRatios)
{
std::vector<VkDescriptorPoolSize> poolSizes;
for (PoolSizeRatio ratio : poolRatios) {
poolSizes.push_back(VkDescriptorPoolSize{
.type = ratio.Type,
.descriptorCount = uint32_t(ratio.Ratio * setCount)
});
}
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = 0;
pool_info.maxSets = setCount;
pool_info.poolSizeCount = (uint32_t)poolSizes.size();
pool_info.pPoolSizes = poolSizes.data();
VkDescriptorPool newPool;
vkCreateDescriptorPool(device, &pool_info, nullptr, &newPool);
return newPool;
}
void DescriptorAllocatorGrowable::Init(VkDevice device, uint32_t maxSets, std::span<PoolSizeRatio> poolRatios)
{
Ratios.clear();
for (auto r : poolRatios) {
Ratios.push_back(r);
}
VkDescriptorPool newPool = CreatePool(device, maxSets, poolRatios);
SetsPerPool = maxSets * 1.5; //grow it next allocation
ReadyPools.push_back(newPool);
}
void DescriptorAllocatorGrowable::ClearPools(VkDevice device)
{
for (auto p : ReadyPools) {
vkResetDescriptorPool(device, p, 0);
}
for (auto p : FullPools) {
vkResetDescriptorPool(device, p, 0);
ReadyPools.push_back(p);
}
FullPools.clear();
}
void DescriptorAllocatorGrowable::DestroyPools(VkDevice device)
{
for (auto p : ReadyPools) {
vkDestroyDescriptorPool(device, p, nullptr);
}
ReadyPools.clear();
for (auto p : FullPools) {
vkDestroyDescriptorPool(device, p, nullptr);
}
FullPools.clear();
}
VkDescriptorSet DescriptorAllocatorGrowable::Allocate(VkDevice device, VkDescriptorSetLayout layout, void* pNext)
{
//get or create a pool to allocate from
VkDescriptorPool poolToUse = GetPool(device);
VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.pNext = pNext;
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = poolToUse;
allocInfo.descriptorSetCount = 1;
allocInfo.pSetLayouts = &layout;
VkDescriptorSet ds;
VkResult result = vkAllocateDescriptorSets(device, &allocInfo, &ds);
//allocation failed. Try again
if (result == VK_ERROR_OUT_OF_POOL_MEMORY || result == VK_ERROR_FRAGMENTED_POOL) {
FullPools.push_back(poolToUse);
poolToUse = GetPool(device);
allocInfo.descriptorPool = poolToUse;
VK_CALL(vkAllocateDescriptorSets(device, &allocInfo, &ds));
}
ReadyPools.push_back(poolToUse);
return ds;
}
void Nuake::DescriptorWriter::WriteImage(int binding, VkImageView image, VkSampler sampler, VkImageLayout layout, VkDescriptorType type)
{
VkDescriptorImageInfo& info = imageInfos.emplace_back(VkDescriptorImageInfo{
.sampler = sampler,
.imageView = image,
.imageLayout = layout
});
VkWriteDescriptorSet write = { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
write.dstBinding = binding;
write.dstSet = VK_NULL_HANDLE; //left empty for now until we need to write it
write.descriptorCount = 1;
write.descriptorType = type;
write.pImageInfo = &info;
writes.push_back(write);
}
void Nuake::DescriptorWriter::WriteBuffer(int binding, VkBuffer buffer, size_t size, size_t offset, VkDescriptorType type)
{
}
void Nuake::DescriptorWriter::Clear()
{
imageInfos.clear();
writes.clear();
bufferInfos.clear();
}
void Nuake::DescriptorWriter::UpdateSet(VkDevice device, VkDescriptorSet set)
{
for (VkWriteDescriptorSet& write : writes) {
write.dstSet = set;
}
vkUpdateDescriptorSets(device, (uint32_t)writes.size(), writes.data(), 0, nullptr);
}

View File

@@ -0,0 +1,47 @@
#pragma once
#include <volk/volk.h>
#include <deque>
#include <span>
#include <vector>
namespace Nuake
{
class DescriptorAllocatorGrowable
{
public:
struct PoolSizeRatio
{
VkDescriptorType Type;
float Ratio;
};
void Init(VkDevice device, uint32_t initialSets, std::span<PoolSizeRatio> poolRatios);
void ClearPools(VkDevice device);
void DestroyPools(VkDevice device);
VkDescriptorSet Allocate(VkDevice device, VkDescriptorSetLayout layout, void* pNext = nullptr);
private:
VkDescriptorPool GetPool(VkDevice device);
VkDescriptorPool CreatePool(VkDevice device, uint32_t setCount, std::span<PoolSizeRatio> poolRatios);
std::vector<PoolSizeRatio> Ratios;
std::vector<VkDescriptorPool> FullPools;
std::vector<VkDescriptorPool> ReadyPools;
uint32_t SetsPerPool;
};
class DescriptorWriter {
std::deque<VkDescriptorImageInfo> imageInfos;
std::deque<VkDescriptorBufferInfo> bufferInfos;
std::vector<VkWriteDescriptorSet> writes;
public:
void WriteImage(int binding, VkImageView image, VkSampler sampler, VkImageLayout layout, VkDescriptorType type);
void WriteBuffer(int binding, VkBuffer buffer, size_t size, size_t offset, VkDescriptorType type);
void Clear();
void UpdateSet(VkDevice device, VkDescriptorSet set);
};
}

View File

@@ -7,7 +7,7 @@
#include "src/Rendering/Vulkan/VulkanAllocatedBuffer.h"
#include "src/Rendering/Vulkan/VulkanImage/VulkanImage.h"
#include "src/Rendering/Vulkan/VkMesh.h"
#include "src/Rendering/Textures/TextureManager.h"
namespace Nuake
{
@@ -120,7 +120,7 @@ namespace Nuake
}
Logger::Log("Mesh with ID does not exist", "vulkan", CRITICAL);
return nullptr;
return TextureManager::Get()->GetTexture2("missing_texture");
}
};
}

View File

@@ -120,7 +120,7 @@ VulkanImage::VulkanImage(ImageFormat inFormat, Vector2 inSize, ImageUsage usage)
vmaCreateImage(VulkanAllocator::Get().GetAllocator(), &imgCreateInfo, &imgAllocInfo, &Image, &Allocation, nullptr);
VkImageViewCreateInfo imageViewCreateInfo;
VkImageViewCreateInfo imageViewCreateInfo = {};
if (usage == ImageUsage::Depth)
{
imageViewCreateInfo = VulkanInit::ImageviewCreateInfo(static_cast<VkFormat>(inFormat), Image, VK_IMAGE_ASPECT_DEPTH_BIT);

View File

@@ -361,6 +361,21 @@ void VkRenderer::InitDescriptors()
CameraBufferDescriptors = GlobalDescriptorAllocator.Allocate(Device, CameraBufferDescriptorLayout);
UpdateDescriptorSets();
for (int i = 0; i < FRAME_OVERLAP; i++)
{
// create a descriptor pool
std::vector<DescriptorAllocatorGrowable::PoolSizeRatio> frame_sizes =
{
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 3 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 4 },
};
Frames[i].FrameDescriptors = DescriptorAllocatorGrowable{};
Frames[i].FrameDescriptors.Init(Device, 1000, frame_sizes);
}
}
void VkRenderer::UpdateDescriptorSets()
@@ -718,6 +733,8 @@ bool VkRenderer::Draw()
FrameSkipped = false;
GetCurrentFrame().FrameDescriptors.ClearPools(Device);
//request image from the swapchain
VkResult result = vkAcquireNextImageKHR(Device, Swapchain, 1000000000, GetCurrentFrame().SwapchainSemaphore, nullptr, &swapchainImageIndex);

View File

@@ -17,6 +17,7 @@
#include "vk_mem_alloc.h"
#include "VkMesh.h"
#include "DescriptorAllocatorGrowable.h"
namespace Nuake
{
@@ -91,6 +92,8 @@ namespace Nuake
VkSemaphore SwapchainSemaphore, RenderSemaphore;
VkFence RenderFence; // CPU wait for next frame
DescriptorAllocatorGrowable FrameDescriptors;
DeletionQueue LocalDeletionQueue; // Local when destroying this frame
};

View File

@@ -10,6 +10,8 @@
#include "src/Scene/Scene.h"
#include "src/Scene/Entities/Entity.h"
#include "src/Rendering/Textures/Material.h"
#include <Tracy.hpp>
#include <src/Scene/Components/ModelComponent.h>
@@ -30,6 +32,7 @@ void VkSceneRenderer::Init()
// Here we will create the pipeline for rendering a scene
LoadShaders();
CreateBuffers();
CreateSamplers();
CreateDescriptors();
CreateBasicPipeline();
@@ -47,14 +50,30 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
auto& cmd = Context.CommandBuffer;
auto& scene = Context.CurrentScene;
auto& vk = VkRenderer::Get();
// Ensure the command buffer is valid
if (cmd == VK_NULL_HANDLE) {
throw std::runtime_error("Invalid command buffer");
}
// Ensure the draw image is valid
if (!vk.DrawImage) {
throw std::runtime_error("Draw image is not initialized");
}
VkRenderingAttachmentInfo colorAttachment = VulkanInit::AttachmentInfo(vk.DrawImage->GetImageView(), nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkRenderingAttachmentInfo depthAttachment = VulkanInit::DepthAttachmentInfo(vk.DepthImage->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(vk.DrawExtent, &colorAttachment, &depthAttachment);
// Ensure the pipeline is valid
if (BasicPipeline == VK_NULL_HANDLE) {
throw std::runtime_error("Basic pipeline is not initialized");
}
vkCmdBeginRendering(cmd, &renderInfo);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, BasicPipeline);
std::vector<VkDescriptorSet> descriptors = { CameraBufferDescriptors, ModelBufferDescriptor };
// Bind camera settings
vkCmdBindDescriptorSets(
@@ -67,7 +86,7 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
0, // dynamicOffsetCount
nullptr // dynamicOffsets
);
// Set viewport
VkViewport viewport = {};
viewport.x = 0;
@@ -76,9 +95,9 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
viewport.height = vk.DrawExtent.height;
viewport.minDepth = 0.f;
viewport.maxDepth = 1.f;
vkCmdSetViewport(cmd, 0, 1, &viewport);
VkRect2D scissor = {};
scissor.offset.x = 0;
scissor.offset.y = 0;
@@ -126,6 +145,22 @@ void VkSceneRenderer::DrawScene()
nullptr // dynamicOffsets
);
// Bind texture descriptor set
Ref<Material> material = m->GetMaterial();
Ref<VulkanImage> albedo = GPUResources::Get().GetTexture(material->AlbedoImage);
//bind a texture
VkDescriptorSet imageSet = vk.GetCurrentFrame().FrameDescriptors.Allocate(vk.GetDevice(), ImageDescriptorLayout);
{
DescriptorWriter writer;
writer.WriteImage(0, albedo->GetImageView(), SamplerNearest, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
writer.UpdateSet(vk.GetDevice(), imageSet);
}
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, BasicPipelineLayout, 3, 1, &imageSet, 0, nullptr);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, BasicPipelineLayout, 4, 1, &SamplerDescriptor, 0, nullptr);
ModelPushConstant modelPushConstant{};
modelPushConstant.Index = ModelMatrixMapping[entity.GetID()];
vkCmdPushConstants(
@@ -183,13 +218,13 @@ void VkSceneRenderer::CreateBasicPipeline()
bufferRange.size = sizeOfThing;
bufferRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkDescriptorSetLayout layouts[] = { CameraBufferDescriptorLayout, ModelBufferDescriptorLayout, TriangleBufferDescriptorLayout };
VkDescriptorSetLayout layouts[] = { CameraBufferDescriptorLayout, ModelBufferDescriptorLayout, TriangleBufferDescriptorLayout, ImageDescriptorLayout, SamplerDescriptorLayout };
VkPipelineLayoutCreateInfo pipeline_layout_info = VulkanInit::PipelineLayoutCreateInfo();
pipeline_layout_info.pPushConstantRanges = &bufferRange;
pipeline_layout_info.pushConstantRangeCount = 1;
pipeline_layout_info.pSetLayouts = layouts;
pipeline_layout_info.setLayoutCount = 3;
pipeline_layout_info.setLayoutCount = 5;
VK_CALL(vkCreatePipelineLayout(VkRenderer::Get().GetDevice(), &pipeline_layout_info, nullptr, &BasicPipelineLayout));
//use the triangle layout we created
@@ -200,13 +235,29 @@ void VkSceneRenderer::CreateBasicPipeline()
pipelineBuilder.SetPolygonMode(VK_POLYGON_MODE_FILL);
pipelineBuilder.SetCullMode(VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE);
pipelineBuilder.SetMultiSamplingNone();
pipelineBuilder.EnableBlendingAlphaBlend();
pipelineBuilder.EnableBlendingAlphaBlend();
pipelineBuilder.SetColorAttachment(static_cast<VkFormat>(VkRenderer::Get().DrawImage->GetFormat()));
pipelineBuilder.SetDepthFormat(static_cast<VkFormat>(VkRenderer::Get().DepthImage->GetFormat()));
pipelineBuilder.EnableDepthTest(true, VK_COMPARE_OP_GREATER_OR_EQUAL);
//pipelineBuilder.DisableDepthTest();
BasicPipeline = pipelineBuilder.BuildPipeline(VkRenderer::Get().GetDevice());
}
void VkSceneRenderer::CreateSamplers()
{
auto device = VkRenderer::Get().GetDevice();
VkSamplerCreateInfo sampler = { .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
sampler.magFilter = VK_FILTER_NEAREST;
sampler.minFilter = VK_FILTER_NEAREST;
vkCreateSampler(device, &sampler, nullptr, &SamplerNearest);
sampler.magFilter = VK_FILTER_LINEAR;
sampler.minFilter = VK_FILTER_LINEAR;
vkCreateSampler(device, &sampler, nullptr, &SamplerLinear);
}
void VkSceneRenderer::CreateDescriptors()
{
auto vk = VkRenderer::Get();
@@ -216,7 +267,7 @@ void VkSceneRenderer::CreateDescriptors()
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
CameraBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL);
CameraBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_VERTEX_BIT);
}
{
@@ -227,16 +278,31 @@ void VkSceneRenderer::CreateDescriptors()
}
{
// Matrices
// Matrices`
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
ModelBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL);
ModelBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_VERTEX_BIT);
}
// Textures
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
ImageDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_FRAGMENT_BIT);
}
{
DescriptorLayoutBuilder builder;
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLER);
SamplerDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_FRAGMENT_BIT);
}
auto allocator = vk.GetDescriptorAllocator();
TriangleBufferDescriptors = allocator.Allocate(device, TriangleBufferDescriptorLayout);
CameraBufferDescriptors = allocator.Allocate(device, CameraBufferDescriptorLayout);
ModelBufferDescriptor = allocator.Allocate(device, ModelBufferDescriptorLayout);
SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout);
//SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout);
// Update descriptor set for camera
VkDescriptorBufferInfo camBufferInfo{};
@@ -253,6 +319,22 @@ void VkSceneRenderer::CreateDescriptors()
bufferWriteCam.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bufferWriteCam.pBufferInfo = &camBufferInfo;
vkUpdateDescriptorSets(device, 1, &bufferWriteCam, 0, nullptr);
// Update Descriptor Set for Texture
VkDescriptorImageInfo textureInfo = {};
textureInfo.sampler = SamplerNearest; // Your VkSampler object
textureInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
// Update Descriptor Set for Sampler
VkWriteDescriptorSet samplerWrite = {};
samplerWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
samplerWrite.dstBinding = 0; // Binding for sampler (in shader)
samplerWrite.dstSet = SamplerDescriptor; // The allocated descriptor set for the sampler
samplerWrite.descriptorCount = 1;
samplerWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
samplerWrite.pImageInfo = &textureInfo; // Sampler info (same as texture)
vkUpdateDescriptorSets(device, 1, &samplerWrite, 0, nullptr);
}
void VkSceneRenderer::UpdateCameraData(const CameraData& data)

View File

@@ -51,6 +51,18 @@ namespace Nuake
ModelData ModelTransforms;
std::map<UUID, uint32_t> ModelMatrixMapping;
VkSampler SamplerLinear;
VkSampler SamplerNearest;
VkDescriptorSet SamplerDescriptor;
VkDescriptorSetLayout SamplerDescriptorLayout;
VkDescriptorSet ImageDescriptor;
VkDescriptorSetLayout ImageDescriptorLayout;
// GBuffer render targets
//Ref<VulkanImage> GBufferAlbedo;
//Ref<VulkanImage> GBufferDepthImage;
public:
VkSceneRenderer();
~VkSceneRenderer();
@@ -67,6 +79,7 @@ namespace Nuake
void LoadShaders();
void CreateBuffers();
void CreateBasicPipeline();
void CreateSamplers();
void CreateDescriptors();
void BuildMatrixBuffer();

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

View File

@@ -1,9 +1,18 @@
[[vk::binding(0, 3)]]
Texture2D<float3> myTexture : register(t1); // Texture binding at slot t0
[[vk::binding(0, 4)]]
SamplerState mySampler : register(s0); // Sampler binding at slot s0
struct PSInput {
float4 Position : SV_Position;
float3 Color : TEXCOORD0;
float2 UV : TEXCOORD1;
};
float4 main(PSInput input) : SV_Target
{
float3 textureColor = myTexture.Sample(mySampler, input.UV);
// Return color with alpha = 1.0f
return float4(input.Color, 1.0f);
return float4(textureColor, 1.0f);
}

View File

@@ -52,10 +52,10 @@ VSOutput main(uint vertexIndex : SV_VertexID)
// 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.Color = normalize(float3(v.position.xyz));
output.UV = float2(v.uv_x, v.uv_y);
return output;
}