Implemented Shadow maps (still needs improvement) #314

Merged
Xenosas1337 merged 22 commits from SP3-1-Rendering into main 2023-01-16 15:40:30 +08:00
8 changed files with 153 additions and 24 deletions
Showing only changes of commit ef8867a7a5 - Show all commits

View File

@ -177,6 +177,21 @@ namespace SHADE
}
}
void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& imageViewAndSampler, uint32_t descIndex) noexcept
{
// Find the target writeDescSet
BindingAndSetHash writeHash = binding;
writeHash |= static_cast<uint64_t>(set) << 32;
auto& writeInfo = updater.writeInfos[updater.writeHashMap.at(writeHash)];
// write sampler and image view
auto& [view, sampler, layout] = imageViewAndSampler;
writeInfo.descImageInfos[descIndex].imageView = view->GetImageView();
writeInfo.descImageInfos[descIndex].sampler = sampler ? sampler->GetVkSampler() : nullptr;
writeInfo.descImageInfos[descIndex].imageLayout = layout;
}
void SHVkDescriptorSetGroup::ModifyWriteDescBuffer(uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept
{
// Find the target writeDescSet

View File

@ -67,6 +67,7 @@ namespace SHADE
void UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept;
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> const& imageViewsAndSamplers) noexcept;
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& imageViewAndSampler, uint32_t descIndex) noexcept;
void ModifyWriteDescBuffer (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;

View File

@ -150,12 +150,26 @@ namespace SHADE
Handle<SHVkDescriptorSetLayout> fontDataDescSetLayout = logicalDevice->CreateDescriptorSetLayout({ fontBitmapBinding, fontMatrixBinding });
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, fontDataDescSetLayout->GetVkHandle(), "[Descriptor Set Layout] Font Data");
// descriptor binding for storing shadow maps
SHVkDescriptorSetLayout::Binding shadowMapBinding
{
.Type = vk::DescriptorType::eCombinedImageSampler,
.Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA,
.DescriptorCount = 200, // we can have up to 2000 textures for now
.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount,
};
// For global data (generic data and textures)
Handle<SHVkDescriptorSetLayout> shadowMapDescLayout = logicalDevice->CreateDescriptorSetLayout({ shadowMapBinding });
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, shadowMapDescLayout->GetVkHandle(), "[Descriptor Set Layout] Shadow Maps");
predefinedLayouts.push_back(staticGlobalLayout);
predefinedLayouts.push_back(lightDataDescSetLayout);
predefinedLayouts.push_back(cameraDataGlobalLayout);
predefinedLayouts.push_back(materialDataPerInstanceLayout);
predefinedLayouts.push_back(fontDataDescSetLayout);
predefinedLayouts.push_back(shadowMapDescLayout);
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts = GetPredefinedDescSetLayouts
(

View File

@ -28,6 +28,7 @@ namespace SHADE
CAMERA = 0x04,
MATERIALS = 0x08,
FONT = 0x10,
SHADOW = 0x20,
};
enum class SystemType

View File

@ -169,6 +169,15 @@ namespace SHADE
/***************************************************************************/
static constexpr uint32_t FONT_MATRIX_DATA = 1;
/***************************************************************************/
/*!
\brief
Descriptor set binding for shadow map images.
*/
/***************************************************************************/
static constexpr uint32_t SHADOW_MAP_IMAGE_SAMPLER_DATA = 0;
};
struct VertexBufferBindings

View File

@ -394,7 +394,11 @@ namespace SHADE
postOffscreenRenderSubSystem->Init(device, renderGraph->GetRenderGraphResource("Scene"), descPool);
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
lightingSubSystem->Init(device, descPool);
lightingSubSystem->Init(device, descPool, samplerCache.GetSampler (device, SHVkSamplerParams
{
// nothing for now
})
);
textRenderingSubSystem = resourceManager.Create<SHTextRenderingSubSystem>();

View File

@ -10,6 +10,9 @@
#include "SHLightComponent.h"
#include "Math/Vector/SHVec4.h"
#include "Math/SHMatrix.h"
#include "Graphics/Images/SHVkImageView.h"
#include "Graphics/MiddleEnd/Textures/SHVkSamplerCache.h"
#include "Graphics/Images/SHVkSampler.h"
namespace SHADE
{
@ -365,6 +368,11 @@ namespace SHADE
}
}
void SHLightingSubSystem::UpdateShadowMapDesc(void) noexcept
{
}
/***************************************************************************/
/*!
@ -375,13 +383,14 @@ namespace SHADE
*/
/***************************************************************************/
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, Handle<SHVkSampler> inShadowMapSampler) noexcept
{
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
logicalDevice = device;
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
#pragma region LIGHTING
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
std::fill (variableSizes.begin(), variableSizes.end(), 1);
@ -418,7 +427,21 @@ namespace SHADE
dynamicOffsets[i].resize(NUM_LIGHT_TYPES + 1); // +1 for the count
}
#pragma endregion
#pragma region SHADOWS
std::vector<uint32_t> shadowDescVariableSizes{ MAX_SHADOWS };
shadowMapDescriptorSet = descPool->Allocate({SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::SHADOW)}, shadowDescVariableSizes);
#ifdef _DEBUG
const auto& SHADOW_MAP_DESC_SETS = shadowMapDescriptorSet->GetVkHandle();
for (int i = 0; i < static_cast<int>(SHADOW_MAP_DESC_SETS.size()); ++i)
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSet, SHADOW_MAP_DESC_SETS[i], "[Descriptor Set] Shadow Map Data Frame #" + std::to_string(i));
#endif
shadowMapSampler = inShadowMapSampler;
//numLightComponents = 0;
#pragma endregion
}
/***************************************************************************/
@ -526,6 +549,36 @@ namespace SHADE
}
void SHLightingSubSystem::AddShadowMap(Handle<SHRenderGraphResource> newShadowMap) noexcept
{
// Add to container of shadow maps
shadowMaps.emplace_back(newShadowMap);
// Just use the image view stored in the resource
Handle<SHVkImageView> const NEW_IMAGE_VIEW = newShadowMap->GetImageView();
// Prepare to write to descriptor
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
static constexpr uint32_t SHADOW_MAP_DESC_SET_INDEX = 0;
uint32_t const SHADOW_MAP_DESC_ARRAY_INDEX = shadowMapImageSamplers.size() - 1;
shadowMapDescriptorSet->ModifyWriteDescImage
(
SHADOW_MAP_DESC_SET_INDEX,
SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA,
shadowMapImageSamplers[SHADOW_MAP_DESC_ARRAY_INDEX],
SHADOW_MAP_DESC_ARRAY_INDEX
);
// TODO: Definitely can be optimized by writing a function that modifies a specific descriptor in the array
shadowMapDescriptorSet->UpdateDescriptorSetImages
(
SHADOW_MAP_DESC_SET_INDEX,
SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA
);
}
Handle<SHVkDescriptorSetGroup> SHLightingSubSystem::GetLightDataDescriptorSet(void) const noexcept
{
return lightingDataDescSet;

View File

@ -6,6 +6,7 @@
#include "SHLightData.h"
#include <array>
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/RenderGraph/SHRenderGraphResource.h"
namespace SHADE
{
@ -16,6 +17,9 @@ namespace SHADE
class SHVkBuffer;
class SHLightComponent;
class SHVkCommandBuffer;
class SHSamplerCache;
class SHVkImageView;
class SHVkSampler;
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
struct SHDirectionalLightData
@ -69,7 +73,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* STATIC MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
static constexpr uint32_t STARTING_NUM_LIGHTS = 50;
static constexpr uint32_t STARTING_NUM_LIGHTS = 50;
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
@ -123,50 +127,78 @@ namespace SHADE
};
private:
/*-----------------------------------------------------------------------*/
/* STATIC MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
static constexpr uint32_t MAX_SHADOWS = 200;
//! logical device used for creation
Handle<SHVkLogicalDevice> logicalDevice;
Handle<SHVkLogicalDevice> logicalDevice;
//! The descriptor set that will hold the lighting data. Each binding will hold a buffer, NUM_FRAMES times the size required.
Handle<SHVkDescriptorSetGroup> lightingDataDescSet;
//! Each type will have some data associated with it for processing
std::array<PerTypeData, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData;
//! Container to store dynamic offsets for binding descriptor sets
DynamicOffsetArray dynamicOffsets;
//! holds the data that represents how many lights are in the scene
std::array<uint32_t, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> lightCountsData;
//! GPU buffer to hold lightCountData
Handle<SHVkBuffer> lightCountsBuffer;
//! For padding in the buffer
uint32_t lightCountsAlignedSize;
Handle<SHVkDescriptorSetGroup> lightingDataDescSet;
//! Each type will have some data associated with it for processing
std::array<PerTypeData, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData;
//! Container to store dynamic offsets for binding descriptor sets
DynamicOffsetArray dynamicOffsets;
//! holds the data that represents how many lights are in the scene
std::array<uint32_t, static_cast<uint32_t>(SH_LIGHT_TYPE::NUM_TYPES)> lightCountsData;
//! GPU buffer to hold lightCountData
Handle<SHVkBuffer> lightCountsBuffer;
//! For padding in the buffer
uint32_t lightCountsAlignedSize;
//! Number of SHLightComponents recorded. If at the beginning of the run function the size returned by the dense
//! set is less than the size recorded, rewrite all light components into the its respective buffers. If its more,
//! don't do anything.
//uint32_t numLightComponents;
//! Handle to sampler that all shadow map descriptors will use
Handle<SHVkSampler> shadowMapSampler;
//! Shadow maps for every light that casts a shadow
std::vector<Handle<SHRenderGraphResource>> shadowMaps;
//! Descriptor sets required to be given to the compute shader for shadow calculation. This will be a descriptor array.
//! It will also be preallocated.
Handle<SHVkDescriptorSetGroup> shadowMapDescriptorSet;
//! Combined image samplers for the texture descriptors
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> shadowMapImageSamplers;
//! Barriers required to transition the resources from whatever layout they are in (probably from VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
//! to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
std::vector<vk::ImageMemoryBarrier> shadowMapMemoryBarriers;
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void UpdateDescSet (uint32_t binding) noexcept;
void ComputeDynamicOffsets (void) noexcept;
void ResetNumLights (void) noexcept;
void UpdateShadowMapDesc (void) noexcept;
public:
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept;
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
void Exit (void) noexcept;
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, Handle<SHVkSampler> inShadowMapSampler) noexcept;
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
void Exit (void) noexcept;
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept;
void AddShadowMap (Handle<SHRenderGraphResource> newShadowMap) noexcept;
//void RemoveShadowMap (uint32_t index) noexcept;
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
Handle<SHVkDescriptorSetGroup> GetLightDataDescriptorSet (void) const noexcept;
};