mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-15 20:08:54 +03:00
Bindless texture buffer now working
This commit is contained in:
@@ -4,11 +4,11 @@
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
void DescriptorLayoutBuilder::AddBinding(uint32_t binding, VkDescriptorType type)
|
||||
void DescriptorLayoutBuilder::AddBinding(uint32_t binding, VkDescriptorType type, uint32_t count)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding newbind{};
|
||||
newbind.binding = binding;
|
||||
newbind.descriptorCount = 1;
|
||||
newbind.descriptorCount = count;
|
||||
newbind.descriptorType = type;
|
||||
|
||||
Bindings.push_back(newbind);
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Nuake
|
||||
{
|
||||
std::vector<VkDescriptorSetLayoutBinding> Bindings;
|
||||
|
||||
void AddBinding(uint32_t binding, VkDescriptorType type);
|
||||
void AddBinding(uint32_t binding, VkDescriptorType type, uint32_t count = 1);
|
||||
void Clear();
|
||||
VkDescriptorSetLayout Build(VkDevice device, VkShaderStageFlags shaderStages, void* pNext = nullptr, VkDescriptorSetLayoutCreateFlags flags = 0);
|
||||
};
|
||||
|
||||
@@ -21,7 +21,8 @@ TextureAttachment::TextureAttachment(const std::string& name, ImageFormat format
|
||||
}
|
||||
|
||||
RenderPass::RenderPass(const std::string& name) :
|
||||
Name(name)
|
||||
Name(name),
|
||||
PushConstantSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,7 +46,7 @@ void RenderPass::ClearAttachments(PassRenderContext& ctx)
|
||||
// TODO: Queue deletion of old textures
|
||||
}
|
||||
|
||||
if (DepthAttachment.Image->GetSize() != ctx.resolution)
|
||||
if (DepthAttachment.Image && DepthAttachment.Image->GetSize() != ctx.resolution)
|
||||
{
|
||||
Ref<VulkanImage> newDepthAttachment = std::make_shared<VulkanImage>(DepthAttachment.Format, ctx.resolution, ImageUsage::Depth);
|
||||
DepthAttachment.Image = newDepthAttachment;
|
||||
@@ -74,7 +75,25 @@ void RenderPass::TransitionAttachments(PassRenderContext& ctx)
|
||||
}
|
||||
|
||||
// Transition depth attachment
|
||||
VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||
if (DepthAttachment.Image)
|
||||
{
|
||||
VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPass::UntransitionAttachments(PassRenderContext& ctx)
|
||||
{
|
||||
for (auto& attachment : Attachments)
|
||||
{
|
||||
// Transform from color attachment to transfer src for next pass
|
||||
VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
|
||||
}
|
||||
|
||||
if (DepthAttachment.Image)
|
||||
{
|
||||
//VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPass::Render(PassRenderContext& ctx)
|
||||
@@ -96,9 +115,13 @@ void RenderPass::Render(PassRenderContext& ctx)
|
||||
renderAttachmentInfos.push_back(attachmentInfo);
|
||||
}
|
||||
|
||||
VkRenderingAttachmentInfo depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(DepthAttachment.Image->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||
VkRenderingAttachmentInfo depthAttachmentInfo = {};
|
||||
if (DepthAttachment.Image)
|
||||
{
|
||||
depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(DepthAttachment.Image->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, &depthAttachmentInfo);
|
||||
VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, !DepthAttachment.Image ? nullptr : &depthAttachmentInfo);
|
||||
renderInfo.colorAttachmentCount = std::size(renderAttachmentInfos);
|
||||
renderInfo.pColorAttachments = renderAttachmentInfos.data();
|
||||
|
||||
@@ -132,12 +155,7 @@ void RenderPass::Render(PassRenderContext& ctx)
|
||||
vkCmdEndRendering(ctx.commandBuffer);
|
||||
// End rendering
|
||||
|
||||
for (auto& attachment : Attachments)
|
||||
{
|
||||
// Transform from color attachment to transfer src for next pass
|
||||
VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
|
||||
}
|
||||
|
||||
|
||||
if (PostRender)
|
||||
{
|
||||
@@ -172,9 +190,9 @@ TextureAttachment& RenderPass::GetAttachment(const std::string& name)
|
||||
return Attachments[0];
|
||||
}
|
||||
|
||||
std::vector<TextureAttachment&> RenderPass::GetAttachments()
|
||||
std::vector<TextureAttachment> RenderPass::GetAttachments()
|
||||
{
|
||||
std::vector<TextureAttachment&> attachentRefs;
|
||||
std::vector<TextureAttachment> attachentRefs;
|
||||
attachentRefs.reserve(Attachments.size());
|
||||
for (auto& attachment : Attachments)
|
||||
{
|
||||
@@ -188,12 +206,12 @@ void RenderPass::AddInput(const std::string& name)
|
||||
InputNames.push_back(name);
|
||||
}
|
||||
|
||||
std::vector<std::string> Nuake::RenderPass::GetInputs()
|
||||
std::vector<std::string> RenderPass::GetInputs()
|
||||
{
|
||||
return InputNames;
|
||||
}
|
||||
|
||||
void RenderPass::SetInput(const std::string& name, TextureAttachment& attachment)
|
||||
void RenderPass::SetInput(const std::string& name, TextureAttachment attachment)
|
||||
{
|
||||
Inputs[name] = attachment;
|
||||
}
|
||||
@@ -207,10 +225,16 @@ void RenderPass::SetShaders(Ref<VulkanShader> vertShader, Ref<VulkanShader> frag
|
||||
void RenderPass::Build()
|
||||
{
|
||||
// Push constant range
|
||||
uint32_t pushRange = 0;
|
||||
VkPushConstantRange bufferRange{};
|
||||
bufferRange.offset = 0;
|
||||
bufferRange.size = PushConstantSize;
|
||||
bufferRange.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
|
||||
if (PushConstantSize > 0)
|
||||
{
|
||||
bufferRange.offset = 0;
|
||||
bufferRange.size = PushConstantSize;
|
||||
bufferRange.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
|
||||
|
||||
pushRange = 1;
|
||||
}
|
||||
|
||||
// TODO: Get the bindless descriptor layout
|
||||
std::vector<VkDescriptorSetLayout> layouts = GPUResources::Get().GetBindlessLayout();
|
||||
@@ -218,7 +242,7 @@ void RenderPass::Build()
|
||||
// Create pipeline layout
|
||||
VkPipelineLayoutCreateInfo pipeline_layout_info = VulkanInit::PipelineLayoutCreateInfo();
|
||||
pipeline_layout_info.pPushConstantRanges = &bufferRange;
|
||||
pipeline_layout_info.pushConstantRangeCount = 1;
|
||||
pipeline_layout_info.pushConstantRangeCount = pushRange;
|
||||
pipeline_layout_info.pSetLayouts = layouts.data();
|
||||
pipeline_layout_info.setLayoutCount = layouts.size();
|
||||
|
||||
@@ -283,26 +307,43 @@ RenderPass& RenderPipeline::GetRenderPass(const std::string& name)
|
||||
|
||||
bool RenderPipeline::Build()
|
||||
{
|
||||
std::map<std::string, TextureAttachment&> attachments;
|
||||
std::map<std::string, TextureAttachment> attachments;
|
||||
for (auto& pass : RenderPasses)
|
||||
{
|
||||
pass.Build();
|
||||
|
||||
for (auto& input : pass.GetInputs())
|
||||
{
|
||||
bool alreadyFoundAttachment = false;
|
||||
if (attachments.find(input) == attachments.end())
|
||||
{
|
||||
Logger::Log("Failed to build RenderPipeline. input " + input + " not found in previous passes.", "vulkan", CRITICAL);
|
||||
return false;
|
||||
if (pass.GetDepthAttachment().Image && pass.GetDepthAttachment().Name == input)
|
||||
{
|
||||
pass.SetInput(input, pass.GetDepthAttachment());
|
||||
alreadyFoundAttachment = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Log("Failed to build RenderPipeline. input " + input + " not found in previous passes.", "vulkan", CRITICAL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pass.SetInput(input, attachments[input]);
|
||||
if (!alreadyFoundAttachment)
|
||||
{
|
||||
pass.SetInput(input, attachments[input]);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& attachment : pass.GetAttachments())
|
||||
{
|
||||
attachments[attachment.Name] = attachment;
|
||||
}
|
||||
|
||||
if (pass.GetDepthAttachment().Image)
|
||||
{
|
||||
attachments[pass.GetDepthAttachment().Name] = pass.GetDepthAttachment();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& pass : RenderPasses)
|
||||
@@ -325,6 +366,7 @@ void RenderPipeline::Execute(PassRenderContext& ctx)
|
||||
pass.ClearAttachments(ctx);
|
||||
pass.TransitionAttachments(ctx);
|
||||
pass.Render(ctx);
|
||||
pass.UntransitionAttachments(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,18 +73,20 @@ namespace Nuake
|
||||
|
||||
void ClearAttachments(PassRenderContext& ctx);
|
||||
void TransitionAttachments(PassRenderContext& ctx);
|
||||
void UntransitionAttachments(PassRenderContext& ctx);
|
||||
void Render(PassRenderContext& ctx);
|
||||
|
||||
public:
|
||||
std::string GetName() const { return Name; }
|
||||
TextureAttachment& AddAttachment(const std::string& name, ImageFormat format, ImageUsage usage = ImageUsage::Default);
|
||||
TextureAttachment& GetAttachment(const std::string& name);
|
||||
std::vector<TextureAttachment&> GetAttachments();
|
||||
std::vector<TextureAttachment> GetAttachments();
|
||||
|
||||
void AddInput(const std::string& name);
|
||||
std::vector<std::string> GetInputs();
|
||||
TextureAttachment& GetDepthAttachment() { return DepthAttachment; }
|
||||
|
||||
void SetInput(const std::string& name, TextureAttachment& attachment);
|
||||
void SetInput(const std::string& name, TextureAttachment attachment);
|
||||
void SetShaders(Ref<VulkanShader> vertShader, Ref<VulkanShader> fragShader);
|
||||
|
||||
template<typename T>
|
||||
@@ -109,9 +111,7 @@ namespace Nuake
|
||||
{
|
||||
private:
|
||||
bool Built;
|
||||
|
||||
std::vector<RenderPass> RenderPasses;
|
||||
|
||||
|
||||
public:
|
||||
RenderPipeline();
|
||||
|
||||
@@ -30,11 +30,13 @@ namespace Nuake
|
||||
VkDescriptorSetLayout ImageDescriptorLayout;
|
||||
VkDescriptorSetLayout SamplerDescriptorLayout;
|
||||
VkDescriptorSetLayout MaterialDescriptorLayout;
|
||||
VkDescriptorSetLayout TexturesDescriptorLayout;
|
||||
|
||||
VkDescriptorSet CameraDescriptor;
|
||||
VkDescriptorSet ModelDescriptor;
|
||||
VkDescriptorSet SamplerDescriptor;
|
||||
VkDescriptorSet MaterialDescriptor;
|
||||
VkDescriptorSet TextureDescriptor;
|
||||
|
||||
public:
|
||||
static GPUResources& Get()
|
||||
@@ -60,6 +62,7 @@ namespace Nuake
|
||||
|
||||
bool AddTexture(Ref<VulkanImage> image);
|
||||
Ref<VulkanImage> GetTexture(const UUID& id);
|
||||
std::vector<Ref<VulkanImage>> GetAllTextures();
|
||||
|
||||
std::vector<VkDescriptorSetLayout> GetBindlessLayout();
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ VulkanImage::VulkanImage(ImageFormat inFormat, Vector2 inSize, ImageUsage usage)
|
||||
else if (usage == ImageUsage::Depth)
|
||||
{
|
||||
drawImageUsages |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
drawImageUsages |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
}
|
||||
|
||||
VkImageCreateInfo imgCreateInfo = VulkanInit::ImageCreateInfo(static_cast<VkFormat>(inFormat), drawImageUsages, vkExtent);
|
||||
|
||||
@@ -514,7 +514,6 @@ void VkRenderer::InitTrianglePipeline()
|
||||
void VkRenderer::DrawScene(RenderContext ctx)
|
||||
{
|
||||
SceneRenderer->BeginScene(ctx);
|
||||
SceneRenderer->DrawScene();
|
||||
SceneRenderer->EndScene();
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@ namespace Nuake
|
||||
constexpr uint32_t FRAME_OVERLAP = 2;
|
||||
constexpr uint32_t MAX_MODEL_MATRIX = 3000;
|
||||
constexpr uint32_t MAX_MATERIAL = 1000;
|
||||
constexpr uint32_t MAX_TEXTURES = 500;
|
||||
|
||||
class VkRenderer
|
||||
{
|
||||
|
||||
@@ -108,6 +108,17 @@ Ref<VulkanImage> GPUResources::GetTexture(const UUID& id)
|
||||
return TextureManager::Get()->GetTexture2("missing_texture");
|
||||
}
|
||||
|
||||
std::vector<Ref<VulkanImage>> GPUResources::GetAllTextures()
|
||||
{
|
||||
std::vector<Ref<VulkanImage>> allImages;
|
||||
allImages.reserve(Images.size());
|
||||
for (const auto& [id, image] : Images)
|
||||
{
|
||||
allImages.push_back(image);
|
||||
}
|
||||
return allImages;
|
||||
}
|
||||
|
||||
void GPUResources::CreateBindlessLayout()
|
||||
{
|
||||
auto& vk = VkRenderer::Get();
|
||||
@@ -153,6 +164,13 @@ void GPUResources::CreateBindlessLayout()
|
||||
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
MaterialDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
|
||||
// Textures
|
||||
{
|
||||
DescriptorLayoutBuilder builder;
|
||||
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_TEXTURES);
|
||||
TexturesDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
|
||||
@@ -163,7 +181,8 @@ std::vector<VkDescriptorSetLayout> GPUResources::GetBindlessLayout()
|
||||
TriangleBufferDescriptorLayout,
|
||||
ImageDescriptorLayout,
|
||||
SamplerDescriptorLayout,
|
||||
MaterialDescriptorLayout
|
||||
MaterialDescriptorLayout,
|
||||
TexturesDescriptorLayout
|
||||
};
|
||||
return layouts;
|
||||
}
|
||||
@@ -52,6 +52,8 @@ void VkSceneRenderer::BeginScene(RenderContext inContext)
|
||||
BuildMatrixBuffer();
|
||||
UpdateTransformBuffer();
|
||||
|
||||
|
||||
|
||||
auto& cmd = Context.CommandBuffer;
|
||||
auto& scene = Context.CurrentScene;
|
||||
auto& vk = VkRenderer::Get();
|
||||
@@ -107,6 +109,8 @@ void VkSceneRenderer::LoadShaders()
|
||||
ShaderCompiler& shaderCompiler = ShaderCompiler::Get();
|
||||
Shaders["basic_frag"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/triangle.frag");
|
||||
Shaders["basic_vert"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/triangle.vert");
|
||||
Shaders["shading_frag"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shading.frag");
|
||||
Shaders["shading_vert"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shading.vert");
|
||||
}
|
||||
|
||||
void VkSceneRenderer::CreateSamplers()
|
||||
@@ -170,12 +174,20 @@ void VkSceneRenderer::CreateDescriptors()
|
||||
MaterialBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
|
||||
//Bindless Textures
|
||||
{
|
||||
DescriptorLayoutBuilder builder;
|
||||
builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_TEXTURES);
|
||||
TextureBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS);
|
||||
}
|
||||
|
||||
auto allocator = vk.GetDescriptorAllocator();
|
||||
TriangleBufferDescriptors = allocator.Allocate(device, TriangleBufferDescriptorLayout);
|
||||
CameraBufferDescriptors = allocator.Allocate(device, CameraBufferDescriptorLayout);
|
||||
ModelBufferDescriptor = allocator.Allocate(device, ModelBufferDescriptorLayout);
|
||||
SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout);
|
||||
MaterialBufferDescriptor = allocator.Allocate(device, MaterialBufferDescriptorLayout);
|
||||
TextureBufferDescriptor = allocator.Allocate(device, TextureBufferDescriptorLayout);
|
||||
//SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout);
|
||||
|
||||
// Update descriptor set for camera
|
||||
@@ -209,6 +221,9 @@ void VkSceneRenderer::CreateDescriptors()
|
||||
samplerWrite.pImageInfo = &textureInfo; // Sampler info (same as texture)
|
||||
|
||||
vkUpdateDescriptorSets(device, 1, &samplerWrite, 0, nullptr);
|
||||
|
||||
// Textures
|
||||
|
||||
}
|
||||
|
||||
void VkSceneRenderer::CreatePipelines()
|
||||
@@ -247,6 +262,17 @@ void VkSceneRenderer::CreatePipelines()
|
||||
0, // dynamicOffsetCount
|
||||
nullptr // dynamicOffsets
|
||||
);
|
||||
|
||||
vkCmdBindDescriptorSets(
|
||||
ctx.commandBuffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
ctx.renderPass->PipelineLayout,
|
||||
6, // firstSet
|
||||
1, // descriptorSetCount
|
||||
&TextureBufferDescriptor, // pointer to the descriptor set(s)
|
||||
0, // dynamicOffsetCount
|
||||
nullptr // dynamicOffsets
|
||||
);
|
||||
});
|
||||
|
||||
gBufferPass.SetRender([&](PassRenderContext& ctx){
|
||||
@@ -321,10 +347,17 @@ 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");
|
||||
shadingPass.AddInput("Normal");
|
||||
shadingPass.AddInput("Material");
|
||||
shadingPass.AddInput("Depth");
|
||||
|
||||
|
||||
shadingPass.SetPreRender([](PassRenderContext& ctx) {});
|
||||
shadingPass.SetRender([](PassRenderContext& ctx) {});
|
||||
GBufferPipeline.Build();
|
||||
}
|
||||
|
||||
@@ -488,6 +521,25 @@ void VkSceneRenderer::UpdateTransformBuffer()
|
||||
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 allTextures = GPUResources::Get().GetAllTextures();
|
||||
std::vector<VkDescriptorImageInfo> imageInfos(allTextures.size());
|
||||
for (size_t i = 0; i < allTextures.size(); i++) {
|
||||
imageInfos[i].imageView = allTextures[i]->GetImageView();
|
||||
imageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
|
||||
VkWriteDescriptorSet write{};
|
||||
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
write.dstSet = TextureBufferDescriptor;
|
||||
write.dstBinding = 0; // Binding 0
|
||||
write.dstArrayElement = 0;
|
||||
write.descriptorCount = static_cast<uint32_t>(imageInfos.size());
|
||||
write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
write.pImageInfo = imageInfos.data();
|
||||
|
||||
vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &write, 0, nullptr);
|
||||
}
|
||||
@@ -74,6 +74,10 @@ namespace Nuake
|
||||
VkDescriptorSet MaterialBufferDescriptor;
|
||||
VkDescriptorSetLayout MaterialBufferDescriptorLayout;
|
||||
|
||||
Ref<AllocatedBuffer> TextureBuffer;
|
||||
VkDescriptorSet TextureBufferDescriptor;
|
||||
VkDescriptorSetLayout TextureBufferDescriptorLayout;
|
||||
|
||||
ModelData ModelTransforms;
|
||||
MaterialData MaterialDataContainer;
|
||||
|
||||
|
||||
103
Resources/Shaders/Vulkan/shading.frag
Normal file
103
Resources/Shaders/Vulkan/shading.frag
Normal file
@@ -0,0 +1,103 @@
|
||||
[[vk::binding(0, 3)]]
|
||||
Texture2D<float4> albedo : register(t1); // Texture binding at slot t0
|
||||
|
||||
[[vk::binding(0, 4)]]
|
||||
SamplerState mySampler : register(s0); // Sampler binding at slot s0
|
||||
|
||||
struct Material
|
||||
{
|
||||
float hasAlbedo;
|
||||
float3 albedo;
|
||||
int hasNormal;
|
||||
int hasMetalness;
|
||||
int hasRoughness;
|
||||
int hasAO;
|
||||
float metalnessValue;
|
||||
float roughnessValue;
|
||||
float aoValue;
|
||||
};
|
||||
[[vk::binding(0, 5)]]
|
||||
StructuredBuffer<Material> material;
|
||||
|
||||
struct PSInput {
|
||||
float4 Position : SV_Position;
|
||||
float3 Color : TEXCOORD0;
|
||||
float2 UV : TEXCOORD1;
|
||||
float3 Normal : TEXCOORD2;
|
||||
float3x3 TBN : TEXCOORD3;
|
||||
};
|
||||
|
||||
struct PSOutput {
|
||||
float4 oColor0 : SV_TARGET;
|
||||
float4 oNormal : SV_TARGET1;
|
||||
float4 oMaterial : SV_TARGET2;
|
||||
};
|
||||
|
||||
struct ModelPushConstant
|
||||
{
|
||||
int modelIndex; // Push constant data
|
||||
int materialIndex;
|
||||
};
|
||||
|
||||
[[vk::push_constant]]
|
||||
ModelPushConstant pushConstants;
|
||||
|
||||
PSOutput main(PSInput input)
|
||||
{
|
||||
PSOutput output;
|
||||
|
||||
Material inMaterial = material[pushConstants.materialIndex];
|
||||
// NORMAL
|
||||
// TODO use TBN matrix
|
||||
float3 normal = float3(0.0, 0.0f, 1.0f);
|
||||
if(inMaterial.hasNormal == 1)
|
||||
{
|
||||
// Sample from texture.
|
||||
}
|
||||
|
||||
normal = mul(input.TBN, normal);
|
||||
normal = normal / 2.0f + 0.5f;
|
||||
output.oNormal = float4(normal, 1.0f);
|
||||
|
||||
// MATERIAL
|
||||
|
||||
// ALBEDO COLOR
|
||||
float4 albedoColor = float4(inMaterial.albedo.xyz, 1.0f);
|
||||
if(inMaterial.hasAlbedo == 1)
|
||||
{
|
||||
float4 albedoTextureSample = albedo.Sample(mySampler, input.UV);
|
||||
|
||||
// Alpha cutout?
|
||||
if(albedoTextureSample.a < 0.001f)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
albedoColor.xyz = albedoTextureSample.xyz;
|
||||
}
|
||||
output.oColor0 = albedoColor;
|
||||
|
||||
// MATERIAL PROPERTIES
|
||||
float metalnessValue = inMaterial.metalnessValue;
|
||||
if(inMaterial.hasMetalness == 1)
|
||||
{
|
||||
// TODO: Sample from metal texture
|
||||
}
|
||||
|
||||
float aoValue = inMaterial.aoValue;
|
||||
if(inMaterial.hasAO == 1)
|
||||
{
|
||||
// TODO: Sample from AO texture
|
||||
}
|
||||
|
||||
float roughnessValue = inMaterial.roughnessValue;
|
||||
if(inMaterial.hasRoughness == 1)
|
||||
{
|
||||
// TODO: Sample from roughness texture
|
||||
}
|
||||
|
||||
float3 materialOuput = float3(inMaterial.metalnessValue, inMaterial.aoValue, inMaterial.roughnessValue);
|
||||
|
||||
output.oMaterial = float4(materialOuput, 1.0f);
|
||||
return output;
|
||||
}
|
||||
70
Resources/Shaders/Vulkan/shading.vert
Normal file
70
Resources/Shaders/Vulkan/shading.vert
Normal file
@@ -0,0 +1,70 @@
|
||||
struct Camera
|
||||
{
|
||||
float4x4 view;
|
||||
float4x4 proj;
|
||||
};
|
||||
[[vk::binding(0, 0)]]
|
||||
StructuredBuffer<Camera> camera : register(t0);
|
||||
|
||||
struct ModelData
|
||||
{
|
||||
float4x4 model;
|
||||
};
|
||||
[[vk::binding(0, 1)]]
|
||||
StructuredBuffer<ModelData> model : register(t1);
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float3 position;
|
||||
float uv_x;
|
||||
float3 normal;
|
||||
float uv_y;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
};
|
||||
|
||||
[[vk::binding(0, 2)]]
|
||||
StructuredBuffer<Vertex> vertexBuffer : register(t2);
|
||||
|
||||
struct ModelPushConstant
|
||||
{
|
||||
int modelIndex; // Push constant data
|
||||
int materialIndex;
|
||||
};
|
||||
|
||||
[[vk::push_constant]]
|
||||
ModelPushConstant pushConstants;
|
||||
|
||||
// Outputs
|
||||
struct VSOutput {
|
||||
float4 Position : SV_Position;
|
||||
float3 Color : TEXCOORD0;
|
||||
float2 UV : TEXCOORD1;
|
||||
float3 Normal : TEXCOORD2;
|
||||
float3x3 TBN : TEXCOORD3;
|
||||
};
|
||||
|
||||
// Main vertex shader
|
||||
VSOutput main(uint vertexIndex : SV_VertexID)
|
||||
{
|
||||
VSOutput output;
|
||||
|
||||
Camera camData = camera[0];
|
||||
|
||||
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.Color = normalize(float3(v.position.xyz));
|
||||
output.UV = float2(v.uv_x, v.uv_y);
|
||||
output.Normal = normalize(v.normal);
|
||||
|
||||
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));
|
||||
return output;
|
||||
}
|
||||
@@ -19,6 +19,9 @@ struct Material
|
||||
[[vk::binding(0, 5)]]
|
||||
StructuredBuffer<Material> material;
|
||||
|
||||
[[vk::binding(0, 6)]]
|
||||
Texture2D textures[];
|
||||
|
||||
struct PSInput {
|
||||
float4 Position : SV_Position;
|
||||
float3 Color : TEXCOORD0;
|
||||
@@ -65,6 +68,7 @@ PSOutput main(PSInput input)
|
||||
float4 albedoColor = float4(inMaterial.albedo.xyz, 1.0f);
|
||||
if(inMaterial.hasAlbedo == 1)
|
||||
{
|
||||
float4 testTexture = textures[pushConstants.modelIndex].Sample(mySampler, input.UV);
|
||||
float4 albedoTextureSample = albedo.Sample(mySampler, input.UV);
|
||||
|
||||
// Alpha cutout?
|
||||
@@ -73,7 +77,7 @@ PSOutput main(PSInput input)
|
||||
discard;
|
||||
}
|
||||
|
||||
albedoColor.xyz = albedoTextureSample.xyz;
|
||||
albedoColor.xyz = testTexture.xyz * albedoTextureSample.xyz;
|
||||
}
|
||||
output.oColor0 = albedoColor;
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
struct Vertex
|
||||
{
|
||||
float3 position;
|
||||
float uv_x;
|
||||
float3 normal;
|
||||
float uv_y;
|
||||
float4 color;
|
||||
};
|
||||
|
||||
// Define the structured buffer for vertices
|
||||
StructuredBuffer<Vertex> vertexBuffer : register(t0); // Binding of vertex buffer (example: t0)
|
||||
|
||||
// Define push constants block
|
||||
cbuffer PushConstants : register(b0) { // Push constants binding (example: b0)
|
||||
float4x4 render_matrix; // Matrix for rendering
|
||||
uint64_t vertexBufferAddress; // Buffer reference address (Vulkan-specific handling required)
|
||||
};
|
||||
|
||||
// Outputs
|
||||
struct VSOutput {
|
||||
float4 Position : SV_Position;
|
||||
float3 Color : TEXCOORD0;
|
||||
float2 UV : TEXCOORD1;
|
||||
};
|
||||
|
||||
// Main vertex shader
|
||||
VSOutput main(uint vertexIndex : SV_VertexID) {
|
||||
VSOutput output;
|
||||
|
||||
// Load vertex data from the buffer
|
||||
Vertex v = vertexBuffer[vertexIndex];
|
||||
|
||||
// Transform and output vertex data
|
||||
output.Position = mul(render_matrix, float4(v.position, 1.0f));
|
||||
output.Color = v.color.xyz;
|
||||
output.UV = float2(v.uv_x, v.uv_y);
|
||||
|
||||
return output;
|
||||
}
|
||||
Reference in New Issue
Block a user