Merge branch 'main' into SP3-4-editor_fix
This commit is contained in:
commit
51489ecb3b
|
@ -0,0 +1,62 @@
|
||||||
|
[Window][MainStatusBar]
|
||||||
|
Pos=0,1060
|
||||||
|
Size=1920,20
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][SHEditorMenuBar]
|
||||||
|
Pos=0,48
|
||||||
|
Size=1920,1012
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Hierarchy Panel]
|
||||||
|
Pos=0,142
|
||||||
|
Size=494,690
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000007,0
|
||||||
|
|
||||||
|
[Window][Debug##Default]
|
||||||
|
Pos=60,60
|
||||||
|
Size=400,400
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Inspector]
|
||||||
|
Pos=1649,48
|
||||||
|
Size=271,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000006,0
|
||||||
|
|
||||||
|
[Window][Profiler]
|
||||||
|
Pos=0,48
|
||||||
|
Size=494,92
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000003,0
|
||||||
|
|
||||||
|
[Window][Viewport]
|
||||||
|
Pos=648,48
|
||||||
|
Size=2519,1319
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000002,0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=496,48
|
||||||
|
Size=1151,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000002,0
|
||||||
|
|
||||||
|
[Window][ Asset Browser]
|
||||||
|
Pos=0,834
|
||||||
|
Size=494,226
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,0
|
||||||
|
|
||||||
|
[Docking][Data]
|
||||||
|
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||||
|
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
|
||||||
|
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=494,1036 Split=Y Selected=0x1E6EB881
|
||||||
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
||||||
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Split=Y Selected=0xE096E5AE
|
||||||
|
DockNode ID=0x00000007 Parent=0x00000004 SizeRef=494,690 Selected=0xE096E5AE
|
||||||
|
DockNode ID=0x00000008 Parent=0x00000004 SizeRef=494,226 Selected=0xB128252A
|
||||||
|
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1151,1036 CentralNode=1 Selected=0xB41284E7
|
||||||
|
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
#include "Physics/Components/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Components/SHColliderComponent.h"
|
#include "Physics/Components/SHColliderComponent.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
#include "Camera/SHCameraComponent.h"
|
#include "Camera/SHCameraComponent.h"
|
||||||
|
@ -158,6 +159,7 @@ namespace Sandbox
|
||||||
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
||||||
|
|
||||||
SHComponentManager::AddComponent<SHCameraComponent>(0);
|
SHComponentManager::AddComponent<SHCameraComponent>(0);
|
||||||
|
SHComponentManager::AddComponent<SHLightComponent>(0);
|
||||||
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
|
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
|
||||||
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
|
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ namespace SHADE
|
||||||
SHVkDebugMessenger::GenMessengerType(SH_DEBUG_MSG_TYPE::T_GENERAL, SH_DEBUG_MSG_TYPE::T_VALIDATION, SH_DEBUG_MSG_TYPE::T_PERFORMANCE));
|
SHVkDebugMessenger::GenMessengerType(SH_DEBUG_MSG_TYPE::T_GENERAL, SH_DEBUG_MSG_TYPE::T_VALIDATION, SH_DEBUG_MSG_TYPE::T_PERFORMANCE));
|
||||||
|
|
||||||
instanceDbgInfo.pfnUserCallback = SHVulkanDebugUtil::GenericDebugCallback;
|
instanceDbgInfo.pfnUserCallback = SHVulkanDebugUtil::GenericDebugCallback;
|
||||||
instanceInfo.pNext = static_cast<vk::DebugUtilsMessengerCreateInfoEXT*>(&instanceDbgInfo);
|
//instanceInfo.pNext = static_cast<vk::DebugUtilsMessengerCreateInfoEXT*>(&instanceDbgInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally create the instance
|
// Finally create the instance
|
||||||
|
|
|
@ -30,200 +30,200 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* SHBatch - Usage Functions */
|
/* SHBatch - Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
||||||
: pipeline{ pipeline }
|
: pipeline{ pipeline }
|
||||||
{
|
{
|
||||||
if (!pipeline)
|
if (!pipeline)
|
||||||
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
||||||
|
|
||||||
// Mark all as dirty
|
// Mark all as dirty
|
||||||
setAllDirtyFlags();
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Add(const SHRenderable* renderable)
|
||||||
|
{
|
||||||
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.Mesh == renderable->Mesh;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create one if not found
|
||||||
|
if (subBatch == subBatches.end())
|
||||||
|
{
|
||||||
|
subBatches.emplace_back(renderable->Mesh);
|
||||||
|
subBatch = subBatches.end() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Add(const SHRenderable* renderable)
|
// Add renderable in
|
||||||
{
|
subBatch->Renderables.insert(renderable->GetEID());
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
|
||||||
{
|
|
||||||
return batch.Mesh == renderable->Mesh;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create one if not found
|
// Also add material instance in
|
||||||
if (subBatch == subBatches.end())
|
referencedMatInstances.insert(renderable->GetMaterial());
|
||||||
|
|
||||||
|
// Mark all as dirty
|
||||||
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Remove(const SHRenderable* renderable)
|
||||||
|
{
|
||||||
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.Mesh == renderable->Mesh;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attempt to remove if it exists
|
||||||
|
if (subBatch == subBatches.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
subBatch->Renderables.erase(renderable->GetEID());
|
||||||
|
|
||||||
|
// Check if other renderables in subBatches contain the same material instance
|
||||||
|
bool matUnused = true;
|
||||||
|
for (const auto& sb : subBatches)
|
||||||
|
for (const auto& rendId : sb.Renderables)
|
||||||
|
{
|
||||||
|
auto rend = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
if (rend)
|
||||||
{
|
{
|
||||||
subBatches.emplace_back(renderable->Mesh);
|
if (rend->GetMaterial() == renderable->GetMaterial())
|
||||||
subBatch = subBatches.end() - 1;
|
{
|
||||||
|
matUnused = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add renderable in
|
// Material is no longer in this library, so we remove it
|
||||||
subBatch->Renderables.insert(renderable->GetEID());
|
if (matUnused)
|
||||||
|
referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial());
|
||||||
|
|
||||||
// Also add material instance in
|
// Mark all as dirty
|
||||||
referencedMatInstances.insert(renderable->GetMaterial());
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
// Mark all as dirty
|
void SHBatch::Clear()
|
||||||
setAllDirtyFlags();
|
{
|
||||||
|
subBatches.clear();
|
||||||
|
|
||||||
|
// Clear CPU buffers
|
||||||
|
drawData.clear();
|
||||||
|
transformData.clear();
|
||||||
|
instancedIntegerData.clear();
|
||||||
|
matPropsData.reset();
|
||||||
|
matPropsDataSize = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Clear GPU buffers
|
||||||
|
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
drawDataBuffer[i].Free();
|
||||||
|
transformDataBuffer[i].Free();
|
||||||
|
instancedIntegerBuffer[i].Free();
|
||||||
|
matPropsBuffer[i].Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Remove(const SHRenderable* renderable)
|
// Check if there are even material properties to update
|
||||||
|
if (!matPropsData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if any materials have changed
|
||||||
|
bool hasChanged = false;
|
||||||
|
for (const auto& material : referencedMatInstances)
|
||||||
{
|
{
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
if (material->HasChanged())
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
{
|
||||||
{
|
hasChanged = true;
|
||||||
return batch.Mesh == renderable->Mesh;
|
break;
|
||||||
});
|
}
|
||||||
|
|
||||||
// Attempt to remove if it exists
|
|
||||||
if (subBatch == subBatches.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
subBatch->Renderables.erase(renderable->GetEID());
|
|
||||||
|
|
||||||
// Check if other renderables in subBatches contain the same material instance
|
|
||||||
bool matUnused = true;
|
|
||||||
for (const auto& sb : subBatches)
|
|
||||||
for (const auto& rendId : sb.Renderables)
|
|
||||||
{
|
|
||||||
auto rend = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
|
||||||
if (rend)
|
|
||||||
{
|
|
||||||
if (rend->GetMaterial() == renderable->GetMaterial())
|
|
||||||
{
|
|
||||||
matUnused = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Material is no longer in this library, so we remove it
|
|
||||||
if (matUnused)
|
|
||||||
referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial());
|
|
||||||
|
|
||||||
// Mark all as dirty
|
|
||||||
setAllDirtyFlags();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Clear()
|
// We need to update all the material buffers if the materials have changed
|
||||||
|
if (hasChanged)
|
||||||
{
|
{
|
||||||
subBatches.clear();
|
for (auto& dirt : matBufferDirty)
|
||||||
|
dirt = true;
|
||||||
// Clear CPU buffers
|
|
||||||
drawData.clear();
|
|
||||||
transformData.clear();
|
|
||||||
eidData.clear();
|
|
||||||
matPropsData.reset();
|
|
||||||
matPropsDataSize = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// Clear GPU buffers
|
|
||||||
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
|
||||||
{
|
|
||||||
drawDataBuffer[i].Free();
|
|
||||||
transformDataBuffer[i].Free();
|
|
||||||
eidBuffer[i].Free();
|
|
||||||
matPropsBuffer[i].Free();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
// Check if this frame's buffer is dirty
|
||||||
{
|
if (!matBufferDirty[frameIndex])
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
return;
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are even material properties to update
|
// Build CPU Buffer
|
||||||
if (!matPropsData)
|
char* propsCurrPtr = matPropsData.get();
|
||||||
return;
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
// Check if any materials have changed
|
{
|
||||||
bool hasChanged = false;
|
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
for (const auto& material : referencedMatInstances)
|
if (renderable)
|
||||||
{
|
{
|
||||||
if (material->HasChanged())
|
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||||
{
|
|
||||||
hasChanged = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// We need to update all the material buffers if the materials have changed
|
|
||||||
if (hasChanged)
|
|
||||||
{
|
{
|
||||||
for (auto& dirt : matBufferDirty)
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
dirt = true;
|
|
||||||
}
|
}
|
||||||
|
propsCurrPtr += singleMatPropAlignedSize;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if this frame's buffer is dirty
|
// Transfer to GPU
|
||||||
if (!matBufferDirty[frameIndex])
|
rebuildMaterialBuffers(frameIndex, descPool);
|
||||||
return;
|
|
||||||
|
|
||||||
// Build CPU Buffer
|
// This frame is updated
|
||||||
char* propsCurrPtr = matPropsData.get();
|
matBufferDirty[frameIndex] = false;
|
||||||
for (auto& subBatch : subBatches)
|
}
|
||||||
for (auto rendId : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
|
||||||
if (renderable)
|
|
||||||
{
|
|
||||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
|
||||||
}
|
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
|
||||||
|
|
||||||
// This frame is updated
|
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
||||||
matBufferDirty[frameIndex] = false;
|
{
|
||||||
}
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
|
||||||
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||||
{
|
return;
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset Transform Data
|
|
||||||
transformData.clear();
|
|
||||||
|
|
||||||
// Populate on the CPU
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
for (auto rendId : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
// Transform
|
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(rendId);
|
|
||||||
if (transform)
|
|
||||||
{
|
|
||||||
transformData.emplace_back(transform->GetTRS());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
|
||||||
transformData.emplace_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
|
||||||
if (transformDataBuffer[frameIndex])
|
|
||||||
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::UpdateEIDBuffer(uint32_t frameIndex)
|
// Reset Transform Data
|
||||||
|
transformData.clear();
|
||||||
|
|
||||||
|
// Populate on the CPU
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Transform
|
||||||
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(rendId);
|
||||||
|
if (transform)
|
||||||
|
{
|
||||||
|
transformData.emplace_back(transform->GetTRS());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||||
|
transformData.emplace_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer to GPU
|
||||||
|
if (transformDataBuffer[frameIndex])
|
||||||
|
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::UpdateInstancedIntegerBuffer(uint32_t frameIndex)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
|
@ -232,233 +232,244 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset Transform Data
|
// Reset Transform Data
|
||||||
eidData.clear();
|
instancedIntegerData.clear();
|
||||||
|
|
||||||
// Populate on the CPU
|
// Populate on the CPU
|
||||||
for (auto& subBatch : subBatches)
|
for (auto& subBatch : subBatches)
|
||||||
for (auto rendId : subBatch.Renderables)
|
for (auto rendId : subBatch.Renderables)
|
||||||
{
|
{
|
||||||
eidData.emplace_back(rendId);
|
auto* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
}
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
rendId,
|
||||||
|
renderable->GetLightLayer()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Transfer to GPU
|
// Transfer to GPU
|
||||||
if (eidBuffer[frameIndex])
|
if (instancedIntegerBuffer[frameIndex])
|
||||||
eidBuffer[frameIndex]->WriteToMemory(eidData.data(), static_cast<EntityID>(eidData.size() * sizeof(EntityID)), 0, 0);
|
instancedIntegerBuffer[frameIndex]->WriteToMemory(instancedIntegerData.data(), static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData)), 0, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
||||||
{
|
return;
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save logical device
|
|
||||||
device = _device;
|
|
||||||
|
|
||||||
// No need to build as there are no changes
|
|
||||||
if (!isDirty[frameIndex])
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Count number of elements
|
|
||||||
size_t numTotalElements = 0;
|
|
||||||
for (const auto& subBatch : subBatches)
|
|
||||||
{
|
|
||||||
numTotalElements += subBatch.Renderables.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate CPU buffers if there are changes
|
|
||||||
if (isCPUBuffersDirty)
|
|
||||||
{
|
|
||||||
// - Draw data
|
|
||||||
drawData.reserve(subBatches.size());
|
|
||||||
drawData.clear();
|
|
||||||
// - Transform data
|
|
||||||
transformData.reserve(numTotalElements);
|
|
||||||
transformData.clear();
|
|
||||||
// - EID data
|
|
||||||
eidData.reserve(numTotalElements);
|
|
||||||
eidData.clear();
|
|
||||||
|
|
||||||
|
|
||||||
// - Material Properties Data
|
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
|
||||||
(
|
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
|
||||||
vk::ShaderStageFlagBits::eFragment
|
|
||||||
);
|
|
||||||
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
|
||||||
Byte matPropTotalBytes = 0;
|
|
||||||
if (!EMPTY_MAT_PROPS)
|
|
||||||
{
|
|
||||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
|
||||||
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
|
||||||
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
|
||||||
if (matPropsDataSize < matPropTotalBytes)
|
|
||||||
{
|
|
||||||
matPropsData.reset(new char[matPropTotalBytes]);
|
|
||||||
matPropsDataSize = matPropTotalBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build Sub Batches
|
|
||||||
uint32_t nextInstanceIndex = 0;
|
|
||||||
char* propsCurrPtr = matPropsData.get();
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
{
|
|
||||||
// Create command
|
|
||||||
const uint32_t CURR_INSTANCES = static_cast<uint32_t>(subBatch.Renderables.size());
|
|
||||||
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
|
||||||
{
|
|
||||||
.indexCount = subBatch.Mesh->IndexCount,
|
|
||||||
.instanceCount = CURR_INSTANCES,
|
|
||||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
|
||||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
|
||||||
.firstInstance = nextInstanceIndex
|
|
||||||
});
|
|
||||||
nextInstanceIndex += CURR_INSTANCES;
|
|
||||||
|
|
||||||
// Fill in buffers (CPU)
|
|
||||||
for (auto rendId : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
// Transform
|
|
||||||
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(rendId);
|
|
||||||
if (!transform)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
|
||||||
transformData.emplace_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transformData.emplace_back(transform->GetTRS());
|
|
||||||
}
|
|
||||||
|
|
||||||
eidData.emplace_back(rendId);
|
|
||||||
|
|
||||||
// Material Properties
|
|
||||||
if (!EMPTY_MAT_PROPS)
|
|
||||||
{
|
|
||||||
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
|
||||||
if (renderable)
|
|
||||||
{
|
|
||||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
|
||||||
}
|
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Successfully update CPU buffers
|
|
||||||
isCPUBuffersDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send all buffered data to the GPU buffers
|
|
||||||
using BuffUsage = vk::BufferUsageFlagBits;
|
|
||||||
// - Draw Data
|
|
||||||
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
|
||||||
BuffUsage::eIndirectBuffer
|
|
||||||
);
|
|
||||||
// - Transform Buffer
|
|
||||||
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
|
||||||
BuffUsage::eVertexBuffer
|
|
||||||
);
|
|
||||||
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(eidData.size() * sizeof(EntityID));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, eidBuffer[frameIndex], eidData.data(), EID_DATA_BYTES,
|
|
||||||
BuffUsage::eVertexBuffer
|
|
||||||
);
|
|
||||||
// - Material Properties Buffer
|
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
|
||||||
|
|
||||||
// Mark this frame as no longer dirty
|
|
||||||
isDirty[frameIndex] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
// Save logical device
|
||||||
/* SHBatch - Usage Functions */
|
device = _device;
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
|
||||||
{
|
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind all required objects before drawing
|
// No need to build as there are no changes
|
||||||
static std::array<uint32_t, 1> dynamicOffset { 0 };
|
if (!isDirty[frameIndex])
|
||||||
cmdBuffer->BindPipeline(pipeline);
|
return;
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::EID, eidBuffer[frameIndex], 0);
|
// Count number of elements
|
||||||
if (matPropsDescSet[frameIndex])
|
size_t numTotalElements = 0;
|
||||||
|
for (const auto& subBatch : subBatches)
|
||||||
|
{
|
||||||
|
numTotalElements += subBatch.Renderables.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate CPU buffers if there are changes
|
||||||
|
if (isCPUBuffersDirty)
|
||||||
|
{
|
||||||
|
// - Draw data
|
||||||
|
drawData.reserve(subBatches.size());
|
||||||
|
drawData.clear();
|
||||||
|
// - Transform data
|
||||||
|
transformData.reserve(numTotalElements);
|
||||||
|
transformData.clear();
|
||||||
|
// - EID data
|
||||||
|
instancedIntegerData.reserve(numTotalElements);
|
||||||
|
instancedIntegerData.clear();
|
||||||
|
|
||||||
|
|
||||||
|
// - Material Properties Data
|
||||||
|
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||||
|
vk::ShaderStageFlagBits::eFragment
|
||||||
|
);
|
||||||
|
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
||||||
|
Byte matPropTotalBytes = 0;
|
||||||
|
if (!EMPTY_MAT_PROPS)
|
||||||
|
{
|
||||||
|
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||||
|
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
||||||
|
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
||||||
|
if (matPropsDataSize < matPropTotalBytes)
|
||||||
{
|
{
|
||||||
cmdBuffer->BindDescriptorSet
|
matPropsData.reset(new char[matPropTotalBytes]);
|
||||||
(
|
matPropsDataSize = matPropTotalBytes;
|
||||||
matPropsDescSet[frameIndex],
|
}
|
||||||
SH_PIPELINE_TYPE::GRAPHICS,
|
}
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
dynamicOffset
|
// Build Sub Batches
|
||||||
|
uint32_t nextInstanceIndex = 0;
|
||||||
|
char* propsCurrPtr = matPropsData.get();
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
{
|
||||||
|
// Create command
|
||||||
|
const uint32_t CURR_INSTANCES = static_cast<uint32_t>(subBatch.Renderables.size());
|
||||||
|
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
||||||
|
{
|
||||||
|
.indexCount = subBatch.Mesh->IndexCount,
|
||||||
|
.instanceCount = CURR_INSTANCES,
|
||||||
|
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||||
|
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||||
|
.firstInstance = nextInstanceIndex
|
||||||
|
});
|
||||||
|
nextInstanceIndex += CURR_INSTANCES;
|
||||||
|
|
||||||
|
// Fill in buffers (CPU)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Transform
|
||||||
|
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(rendId);
|
||||||
|
if (!transform)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||||
|
transformData.emplace_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transformData.emplace_back(transform->GetTRS());
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
rendId,
|
||||||
|
renderable->GetLightLayer()
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
// Material Properties
|
||||||
/* SHBatch - Helper Functions */
|
if (!EMPTY_MAT_PROPS)
|
||||||
/*---------------------------------------------------------------------------------*/
|
{
|
||||||
void SHBatch::setAllDirtyFlags()
|
if (renderable)
|
||||||
{
|
|
||||||
for (bool& dirt : isDirty)
|
|
||||||
dirt = true;
|
|
||||||
isCPUBuffersDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
|
||||||
{
|
|
||||||
if (matPropsData)
|
|
||||||
{
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
|
||||||
vk::BufferUsageFlagBits::eStorageBuffer
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!matPropsDescSet[frameIndex])
|
|
||||||
{
|
{
|
||||||
matPropsDescSet[frameIndex] = descPool->Allocate
|
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||||
(
|
|
||||||
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
|
||||||
{ 0 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
else
|
||||||
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
{
|
||||||
(
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
}
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
propsCurrPtr += singleMatPropAlignedSize;
|
||||||
bufferList,
|
}
|
||||||
0, static_cast<uint32_t>(matPropsDataSize)
|
|
||||||
);
|
|
||||||
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
|
||||||
(
|
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successfully update CPU buffers
|
||||||
|
isCPUBuffersDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send all buffered data to the GPU buffers
|
||||||
|
using BuffUsage = vk::BufferUsageFlagBits;
|
||||||
|
// - Draw Data
|
||||||
|
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
||||||
|
BuffUsage::eIndirectBuffer
|
||||||
|
);
|
||||||
|
// - Transform Buffer
|
||||||
|
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer
|
||||||
|
);
|
||||||
|
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, instancedIntegerBuffer[frameIndex], instancedIntegerData.data(), EID_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer
|
||||||
|
);
|
||||||
|
// - Material Properties Buffer
|
||||||
|
rebuildMaterialBuffers(frameIndex, descPool);
|
||||||
|
|
||||||
|
// Mark this frame as no longer dirty
|
||||||
|
isDirty[frameIndex] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind all required objects before drawing
|
||||||
|
static std::array<uint32_t, 1> dynamicOffset{ 0 };
|
||||||
|
cmdBuffer->BindPipeline(pipeline);
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
||||||
|
if (matPropsDescSet[frameIndex])
|
||||||
|
{
|
||||||
|
cmdBuffer->BindDescriptorSet
|
||||||
|
(
|
||||||
|
matPropsDescSet[frameIndex],
|
||||||
|
SH_PIPELINE_TYPE::GRAPHICS,
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
dynamicOffset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHBatch::setAllDirtyFlags()
|
||||||
|
{
|
||||||
|
for (bool& dirt : isDirty)
|
||||||
|
dirt = true;
|
||||||
|
isCPUBuffersDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
|
{
|
||||||
|
if (matPropsData)
|
||||||
|
{
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||||
|
vk::BufferUsageFlagBits::eStorageBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!matPropsDescSet[frameIndex])
|
||||||
|
{
|
||||||
|
matPropsDescSet[frameIndex] = descPool->Allocate
|
||||||
|
(
|
||||||
|
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
||||||
|
{ 0 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
||||||
|
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||||
|
bufferList,
|
||||||
|
0, static_cast<uint32_t>(matPropsDataSize)
|
||||||
|
);
|
||||||
|
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
#include "ECS_Base/SHECSMacros.h"
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -79,7 +80,7 @@ namespace SHADE
|
||||||
void Clear();
|
void Clear();
|
||||||
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||||
void UpdateEIDBuffer(uint32_t frameIndex);
|
void UpdateInstancedIntegerBuffer(uint32_t frameIndex);
|
||||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
||||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||||
|
|
||||||
|
@ -111,7 +112,7 @@ namespace SHADE
|
||||||
// CPU Buffers
|
// CPU Buffers
|
||||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||||
std::vector<SHMatrix> transformData;
|
std::vector<SHMatrix> transformData;
|
||||||
std::vector<EntityID> eidData;
|
std::vector<SHInstancedIntegerData> instancedIntegerData;
|
||||||
std::unique_ptr<char> matPropsData;
|
std::unique_ptr<char> matPropsData;
|
||||||
Byte matPropsDataSize = 0;
|
Byte matPropsDataSize = 0;
|
||||||
Byte singleMatPropAlignedSize = 0;
|
Byte singleMatPropAlignedSize = 0;
|
||||||
|
@ -120,7 +121,7 @@ namespace SHADE
|
||||||
// GPU Buffers
|
// GPU Buffers
|
||||||
TripleBuffer drawDataBuffer;
|
TripleBuffer drawDataBuffer;
|
||||||
TripleBuffer transformDataBuffer;
|
TripleBuffer transformDataBuffer;
|
||||||
TripleBuffer eidBuffer;
|
TripleBuffer instancedIntegerBuffer;
|
||||||
TripleBuffer matPropsBuffer;
|
TripleBuffer matPropsBuffer;
|
||||||
TripleDescSet matPropsDescSet;
|
TripleDescSet matPropsDescSet;
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
||||||
batch.UpdateTransformBuffer(frameIndex);
|
batch.UpdateTransformBuffer(frameIndex);
|
||||||
batch.UpdateEIDBuffer(frameIndex);
|
batch.UpdateInstancedIntegerBuffer(frameIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Graphics/Pipeline/SHPipelineState.h"
|
#include "Graphics/Pipeline/SHPipelineState.h"
|
||||||
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightData.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -45,16 +47,35 @@ namespace SHADE
|
||||||
// For global data (generic data and textures)
|
// For global data (generic data and textures)
|
||||||
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
|
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
|
||||||
|
|
||||||
SHVkDescriptorSetLayout::Binding lightBinding
|
std::vector<SHVkDescriptorSetLayout::Binding> lightBindings{};
|
||||||
|
for (uint32_t i = 0; i < SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i)
|
||||||
{
|
{
|
||||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
lightBindings.push_back (SHVkDescriptorSetLayout::Binding
|
||||||
.Stage = vk::ShaderStageFlagBits::eFragment,
|
{
|
||||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::LIGHTS_DATA,
|
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
.DescriptorCount = 1,
|
.Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
};
|
.BindPoint = i,
|
||||||
|
.DescriptorCount = 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//SHVkDescriptorSetLayout::Binding pointLightBinding
|
||||||
|
//{
|
||||||
|
// .Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
|
// .Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
// .BindPoint = SHGraphicsConstants::DescriptorSetBindings::POINT_LIGHT_DATA,
|
||||||
|
// .DescriptorCount = 1,
|
||||||
|
//};
|
||||||
|
|
||||||
|
//SHVkDescriptorSetLayout::Binding spotLightBinding
|
||||||
|
//{
|
||||||
|
// .Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
|
// .Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
|
// .BindPoint = SHGraphicsConstants::DescriptorSetBindings::SPOT_LIGHT_DATA,
|
||||||
|
// .DescriptorCount = 1,
|
||||||
|
//};
|
||||||
|
|
||||||
// For Dynamic global data (lights)
|
// For Dynamic global data (lights)
|
||||||
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, { lightBinding });
|
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings);
|
||||||
|
|
||||||
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
||||||
{
|
{
|
||||||
|
@ -94,7 +115,7 @@ namespace SHADE
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
||||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
||||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // EID at binding 8
|
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
void SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
|
|
|
@ -94,14 +94,32 @@ namespace SHADE
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
|
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
|
||||||
|
|
||||||
/***************************************************************************/
|
///***************************************************************************/
|
||||||
/*!
|
///*!
|
||||||
\brief
|
// \brief
|
||||||
DescriptorSet binding for lights.
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
*/
|
//*/
|
||||||
/***************************************************************************/
|
///***************************************************************************/
|
||||||
static constexpr uint32_t LIGHTS_DATA = 0;
|
//static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0;
|
||||||
|
|
||||||
|
///***************************************************************************/
|
||||||
|
///*!
|
||||||
|
// \brief
|
||||||
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
|
//*/
|
||||||
|
///***************************************************************************/
|
||||||
|
//static constexpr uint32_t POINT_LIGHT_DATA = 1;
|
||||||
|
|
||||||
|
///***************************************************************************/
|
||||||
|
///*!
|
||||||
|
// \brief
|
||||||
|
// DescriptorSet binding for directional lights.
|
||||||
|
|
||||||
|
//*/
|
||||||
|
///***************************************************************************/
|
||||||
|
//static constexpr uint32_t SPOT_LIGHT_DATA = 2;
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@ -164,7 +182,7 @@ namespace SHADE
|
||||||
Vertex buffer bindings for the eid buffer.
|
Vertex buffer bindings for the eid buffer.
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t EID = 5;
|
static constexpr uint32_t INTEGER_DATA = 5;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Graphics/Images/SHVkSampler.h"
|
#include "Graphics/Images/SHVkSampler.h"
|
||||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -124,14 +125,17 @@ namespace SHADE
|
||||||
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
|
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
|
||||||
|
|
||||||
shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
||||||
|
shaderSourceLibrary.LoadShader(3, "PureCopyCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
||||||
|
|
||||||
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
||||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
||||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
||||||
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
||||||
|
auto pureCopy = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
|
||||||
cubeVS->Reflect();
|
cubeVS->Reflect();
|
||||||
cubeFS->Reflect();
|
cubeFS->Reflect();
|
||||||
greyscale->Reflect();
|
greyscale->Reflect();
|
||||||
|
pureCopy->Reflect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
||||||
|
@ -172,21 +176,32 @@ namespace SHADE
|
||||||
|
|
||||||
// Initialize world render graph
|
// Initialize world render graph
|
||||||
worldRenderGraph->Init(device, swapchain);
|
worldRenderGraph->Init(device, swapchain);
|
||||||
worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||||
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||||
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||||
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||||
|
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||||
|
|
||||||
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
|
auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", { "Light Layer Indices", "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
|
||||||
|
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
|
||||||
|
gBufferSubpass->AddColorOutput("Scene Pre-Process");
|
||||||
|
gBufferSubpass->AddColorOutput("Entity ID");
|
||||||
|
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||||
|
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
||||||
|
|
||||||
//First subpass to write to G-Buffer
|
//// kirsch
|
||||||
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
|
//auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
||||||
gBufferWriteSubpass->AddColorOutput("Scene Pre-Process");
|
//gBufferNode->AddNodeCompute(kirschShader, { "Scene Pre-Process", "Scene" });
|
||||||
gBufferWriteSubpass->AddColorOutput("Entity ID");
|
|
||||||
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
// copy
|
||||||
|
auto pureCopyShader = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl");
|
||||||
|
gBufferNode->AddNodeCompute(pureCopyShader, { "Scene Pre-Process", "Scene" });
|
||||||
|
|
||||||
|
|
||||||
|
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors
|
||||||
|
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
|
||||||
|
dummySubpass->AddInput("Scene");
|
||||||
|
|
||||||
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
|
||||||
node->AddNodeCompute (greyscale, {"Scene Pre-Process", "Scene"});
|
|
||||||
|
|
||||||
// Generate world render graph
|
// Generate world render graph
|
||||||
worldRenderGraph->Generate();
|
worldRenderGraph->Generate();
|
||||||
|
@ -200,7 +215,7 @@ namespace SHADE
|
||||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
||||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
||||||
|
|
||||||
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
|
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,11 +246,15 @@ namespace SHADE
|
||||||
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
||||||
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
|
cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]);
|
||||||
|
|
||||||
|
// Mouse picking system for the editor (Will still run with editor disabled)
|
||||||
mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
|
mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID"));
|
||||||
|
|
||||||
// Register the post offscreen render to the system
|
// Register the post offscreen render to the system
|
||||||
postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
|
postOffscreenRender = resourceManager.Create<SHPostOffscreenRenderSystem>();
|
||||||
postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
|
postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool);
|
||||||
|
|
||||||
|
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
|
||||||
|
lightingSubSystem->Init(device, descPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
|
@ -353,10 +372,12 @@ namespace SHADE
|
||||||
// Begin recording the command buffer
|
// Begin recording the command buffer
|
||||||
currentCmdBuffer->BeginRecording();
|
currentCmdBuffer->BeginRecording();
|
||||||
|
|
||||||
|
// set viewport and scissor
|
||||||
uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
|
uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
|
||||||
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
|
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
|
||||||
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
|
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
|
||||||
|
|
||||||
|
// Force set the pipeline layout
|
||||||
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
|
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
|
||||||
|
|
||||||
// Bind all the buffers required for meshes
|
// Bind all the buffers required for meshes
|
||||||
|
@ -368,6 +389,8 @@ namespace SHADE
|
||||||
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind the descriptor set for lights
|
||||||
|
lightingSubSystem->Run(currentCmdBuffer, frameIndex);
|
||||||
|
|
||||||
// Bind textures
|
// Bind textures
|
||||||
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
||||||
|
@ -401,7 +424,7 @@ namespace SHADE
|
||||||
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Draw first
|
// Draw the scene
|
||||||
renderers[renIndex]->Draw(frameIndex, descPool);
|
renderers[renIndex]->Draw(frameIndex, descPool);
|
||||||
|
|
||||||
// End the command buffer recording
|
// End the command buffer recording
|
||||||
|
|
|
@ -32,6 +32,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "../Textures/SHTextureLibrary.h"
|
#include "../Textures/SHTextureLibrary.h"
|
||||||
#include "../Textures/SHVkSamplerCache.h"
|
#include "../Textures/SHVkSamplerCache.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
|
||||||
|
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -351,6 +352,7 @@ namespace SHADE
|
||||||
// Sub systems
|
// Sub systems
|
||||||
Handle<SHMousePickSystem> mousePickSystem;
|
Handle<SHMousePickSystem> mousePickSystem;
|
||||||
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
|
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
|
||||||
|
Handle<SHLightingSubSystem> lightingSubSystem;
|
||||||
|
|
||||||
uint32_t resizeWidth;
|
uint32_t resizeWidth;
|
||||||
uint32_t resizeHeight;
|
uint32_t resizeHeight;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
EntityID eid;
|
||||||
|
uint32_t lightLayer;
|
||||||
|
};
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
#include "Graphics/SHVkUtil.h"
|
#include "Graphics/SHVkUtil.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
|
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
|
||||||
|
//#include "Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -53,7 +54,7 @@ namespace SHADE
|
||||||
// wait for the copy to be done
|
// wait for the copy to be done
|
||||||
afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
|
afterCopyFence->Wait(true, std::numeric_limits<uint64_t>::max());
|
||||||
|
|
||||||
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<uint32_t>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
|
pickedEID = imageDataDstBuffer->GetDataFromMappedPointer<EntityID>(static_cast<uint32_t>(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast<uint32_t>(viewportMousePos.x));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
std::vector combinedImageSampler
|
std::vector combinedImageSampler
|
||||||
{
|
{
|
||||||
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eGeneral),
|
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change
|
// Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace SHADE
|
||||||
sharedMaterial = {};
|
sharedMaterial = {};
|
||||||
material = {};
|
material = {};
|
||||||
oldMaterial = {};
|
oldMaterial = {};
|
||||||
|
|
||||||
|
lightLayer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRenderable::OnDestroy()
|
void SHRenderable::OnDestroy()
|
||||||
|
@ -91,6 +93,11 @@ namespace SHADE
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t SHRenderable::GetLightLayer(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightLayer;
|
||||||
|
}
|
||||||
|
|
||||||
void SHRenderable::ResetChangedFlag()
|
void SHRenderable::ResetChangedFlag()
|
||||||
{
|
{
|
||||||
materialChanged = false;
|
materialChanged = false;
|
||||||
|
|
|
@ -56,6 +56,7 @@ namespace SHADE
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
bool WasMaterialChanged() const noexcept { return materialChanged; }
|
bool WasMaterialChanged() const noexcept { return materialChanged; }
|
||||||
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
|
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
|
||||||
|
uint8_t GetLightLayer (void) const noexcept;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Batcher Dispatcher Functions */
|
/* Batcher Dispatcher Functions */
|
||||||
|
@ -75,6 +76,7 @@ namespace SHADE
|
||||||
Handle<SHMaterialInstance> material;
|
Handle<SHMaterialInstance> material;
|
||||||
bool materialChanged = true;
|
bool materialChanged = true;
|
||||||
Handle<SHMaterialInstance> oldMaterial;
|
Handle<SHMaterialInstance> oldMaterial;
|
||||||
|
uint8_t lightLayer;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::OnCreate(void)
|
||||||
|
{
|
||||||
|
lightData.Reset();
|
||||||
|
SetType(SH_LIGHT_TYPE::DIRECTIONAL);
|
||||||
|
indexInBuffer = std::numeric_limits<uint32_t>::max();
|
||||||
|
active = true;
|
||||||
|
Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::OnDestroy(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetPosition(SHVec3 position) noexcept
|
||||||
|
{
|
||||||
|
lightData.position = position;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
lightData.type = type;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetDirection(SHVec3 direction) noexcept
|
||||||
|
{
|
||||||
|
lightData.direction = direction;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetDiffuseColor(SHVec4 diffuseColor) noexcept
|
||||||
|
{
|
||||||
|
lightData.diffuseColor = diffuseColor;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::ModifyLayer(uint8_t layerIndex, bool value) noexcept
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
lightData.cullingMask |= (1u << layerIndex);
|
||||||
|
else
|
||||||
|
lightData.cullingMask &= ~(1u << layerIndex);
|
||||||
|
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::SetAllLayers(void) noexcept
|
||||||
|
{
|
||||||
|
lightData.cullingMask = std::numeric_limits<uint32_t>::max();
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHLightComponent::ClearAllLayers(void) noexcept
|
||||||
|
{
|
||||||
|
lightData.cullingMask = 0;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::MakeDirty(void) noexcept
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::ClearDirtyFlag(void) noexcept
|
||||||
|
{
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::Unbind(void) noexcept
|
||||||
|
{
|
||||||
|
bound = false;
|
||||||
|
MakeDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept
|
||||||
|
{
|
||||||
|
bound = true;
|
||||||
|
indexInBuffer = inIndexInBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightComponent::SetActive(bool flag) noexcept
|
||||||
|
{
|
||||||
|
MakeDirty();
|
||||||
|
active = flag;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHLightComponent::IsDirty(void) const noexcept
|
||||||
|
{
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHLightComponent::GetBound(void) const noexcept
|
||||||
|
{
|
||||||
|
return bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept
|
||||||
|
{
|
||||||
|
return indexInBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
|
||||||
|
class SH_API SHLightComponent final : public SHComponent
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
//! General data for the light. This will purely be CPU bound. Whatever gets sent to the
|
||||||
|
//! GPU depends on the type of the light.
|
||||||
|
SHLightData lightData;
|
||||||
|
|
||||||
|
//! Since the lighting system is gonna be self contained and light weight, we store this
|
||||||
|
//! so that we only write this to the CPU buffer when this light component change, we don't
|
||||||
|
//! rewrite everything. However we still write to the GPU buffer when everything changes.
|
||||||
|
uint32_t indexInBuffer;
|
||||||
|
|
||||||
|
//! If the light component changed some value we mark this true.
|
||||||
|
bool dirty;
|
||||||
|
|
||||||
|
//! If the light's data is already in the buffers, this will be set to true.
|
||||||
|
bool bound;
|
||||||
|
|
||||||
|
//! If the light is active, this is true.
|
||||||
|
bool active;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* LIFECYCLE FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void OnCreate (void) override final;
|
||||||
|
void OnDestroy (void) override final;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* SETTERS AND GETTERS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void SetPosition (SHVec3 position) noexcept;
|
||||||
|
void SetType (SH_LIGHT_TYPE type) noexcept;
|
||||||
|
void SetDirection (SHVec3 direction) noexcept;
|
||||||
|
void SetDiffuseColor (SHVec4 diffuseColor) noexcept;
|
||||||
|
void ModifyLayer (uint8_t layerIndex, bool value) noexcept;
|
||||||
|
void SetAllLayers (void) noexcept;
|
||||||
|
void ClearAllLayers (void) noexcept;
|
||||||
|
void MakeDirty (void) noexcept;
|
||||||
|
void ClearDirtyFlag (void) noexcept;
|
||||||
|
void Unbind (void) noexcept;
|
||||||
|
void SetBound (uint32_t inIndexInBuffer) noexcept;
|
||||||
|
void SetActive (bool flag) noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
SHLightData const& GetLightData (void) const noexcept;
|
||||||
|
bool IsDirty (void) const noexcept;
|
||||||
|
bool GetBound (void) const noexcept;
|
||||||
|
uint32_t GetIndexInBuffer (void) const noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
void SHLightData::Reset(void) noexcept
|
||||||
|
{
|
||||||
|
// no culling is done.
|
||||||
|
cullingMask = std::numeric_limits<uint32_t>::max();
|
||||||
|
|
||||||
|
// reset position to 0
|
||||||
|
position = SHVec3::Zero;
|
||||||
|
|
||||||
|
// direction just point in positive z axis
|
||||||
|
direction = SHVec3::Forward;
|
||||||
|
|
||||||
|
// Diffuse color set to 1
|
||||||
|
diffuseColor = SHVec4::One;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
enum class SH_LIGHT_TYPE : uint32_t
|
||||||
|
{
|
||||||
|
DIRECTIONAL = 0,
|
||||||
|
POINT,
|
||||||
|
SPOT,
|
||||||
|
NUM_TYPES
|
||||||
|
};
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\class
|
||||||
|
Every light will essentially be using this struct. However, when passing
|
||||||
|
light data over to the GPU, the light data will be split according to
|
||||||
|
type for more optimal cache access.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
struct SHLightData
|
||||||
|
{
|
||||||
|
//! position of the light
|
||||||
|
SHVec3 position;
|
||||||
|
|
||||||
|
//! Type of the light
|
||||||
|
SH_LIGHT_TYPE type;
|
||||||
|
|
||||||
|
//! direction of the light
|
||||||
|
SHVec3 direction;
|
||||||
|
|
||||||
|
//! Each bit in this 32 bit field will represent a layer. If the bit is set,
|
||||||
|
//! when a fragment is being evaluated, the shader will use the fragment's
|
||||||
|
//! layer value to AND with the light's. If result is 1, do lighting calculations.
|
||||||
|
uint32_t cullingMask;
|
||||||
|
|
||||||
|
//! Diffuse color emitted by the light
|
||||||
|
SHVec4 diffuseColor;
|
||||||
|
|
||||||
|
void Reset (void) noexcept;
|
||||||
|
//! TODO:
|
||||||
|
//! - Add cut off. (inner and outer).
|
||||||
|
//! - Add constant, linear and quadratic for attenuation
|
||||||
|
//! - Specular color if needed. see below.
|
||||||
|
|
||||||
|
//! Specular color
|
||||||
|
//SHVec4 specularColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,431 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHLightingSubSystem.h"
|
||||||
|
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||||
|
#include "Tools/SHUtilities.h"
|
||||||
|
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||||
|
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||||
|
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
|
#include "SHLightComponent.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
This function takes an address in the CPU container and writes light
|
||||||
|
component data to it. What gets written depends on the light type.
|
||||||
|
|
||||||
|
\param address
|
||||||
|
The address to write to.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component with the data to write from.
|
||||||
|
|
||||||
|
\param lightType
|
||||||
|
The type of the light
|
||||||
|
|
||||||
|
\return
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::WriteLightToAddress(void* address, SHLightComponent* lightComp) noexcept
|
||||||
|
{
|
||||||
|
auto const& lightData = lightComp->GetLightData();
|
||||||
|
switch (lightData.type)
|
||||||
|
{
|
||||||
|
case SH_LIGHT_TYPE::DIRECTIONAL:
|
||||||
|
{
|
||||||
|
SHDirectionalLightData* lightPtr = reinterpret_cast<SHDirectionalLightData*>(address);
|
||||||
|
|
||||||
|
lightPtr->cullingMask = lightData.cullingMask;
|
||||||
|
lightPtr->direction = lightData.direction;
|
||||||
|
lightPtr->diffuseColor = lightData.diffuseColor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SH_LIGHT_TYPE::POINT:
|
||||||
|
break;
|
||||||
|
case SH_LIGHT_TYPE::SPOT:
|
||||||
|
break;
|
||||||
|
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Initializes type, intermediate data and buffer. dirty will be true.
|
||||||
|
|
||||||
|
\param lightType
|
||||||
|
type of the light.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::InitializeData(Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
// initialize the type
|
||||||
|
lightType = type;
|
||||||
|
|
||||||
|
// boilerplate
|
||||||
|
intermediateData = nullptr;
|
||||||
|
|
||||||
|
// initialize alignment
|
||||||
|
lightDataAlignmentSize = logicalDevice->PadSSBOSize(GetLightTypeSize(type));
|
||||||
|
|
||||||
|
// So create some data!
|
||||||
|
Expand(logicalDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Expands both the CPU container and the GPU buffer when the number of
|
||||||
|
lights have exceeded the capacity.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::Expand(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
|
{
|
||||||
|
if (lightDataAlignmentSize == 0)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR ("One of the types of lights have not been accounted for. Make sure lightDataAlignmentSize is not nullptr.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we want to wait for the command buffers to finish using the buffers first
|
||||||
|
logicalDevice->WaitIdle();
|
||||||
|
|
||||||
|
// First time we are initializing lights
|
||||||
|
if (intermediateData == nullptr)
|
||||||
|
{
|
||||||
|
// max lights should start of at STARTING_NUM_LIGHTS lights
|
||||||
|
maxLights = STARTING_NUM_LIGHTS;
|
||||||
|
numLights = 0;
|
||||||
|
|
||||||
|
// Initialize the data for lights
|
||||||
|
intermediateData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * maxLights);
|
||||||
|
|
||||||
|
// We want to initialize 3 times the amount of data required.
|
||||||
|
dataBuffer = logicalDevice->CreateBuffer(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// save old number of lights
|
||||||
|
uint32_t const OLD_MAX_LIGHTS = maxLights;
|
||||||
|
|
||||||
|
// before we increase the number of lights, create space to store old data.
|
||||||
|
std::unique_ptr<uint8_t[]> oldData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// copy data over.
|
||||||
|
std::memcpy (oldData.get(), intermediateData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// now we start to expand....
|
||||||
|
|
||||||
|
// double space for lights
|
||||||
|
maxLights *= 2;
|
||||||
|
|
||||||
|
// destroy old data and initialize container for double the amount of data.
|
||||||
|
intermediateData = std::make_unique<uint8_t[]>(lightDataAlignmentSize * maxLights);
|
||||||
|
|
||||||
|
// copy old data to new container
|
||||||
|
std::memcpy(intermediateData.get(), oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
|
||||||
|
// Resize the GPU buffer. TODO: Replace with Resize no copy here
|
||||||
|
dataBuffer->ResizeReplace(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Gets the size required to store data for a light type.
|
||||||
|
|
||||||
|
\param type
|
||||||
|
Type of a light.
|
||||||
|
|
||||||
|
\return
|
||||||
|
Size required to store a light based on type.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetLightTypeSize(SH_LIGHT_TYPE type) noexcept
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case SH_LIGHT_TYPE::DIRECTIONAL:
|
||||||
|
// TOOD: Change after creating point light struct
|
||||||
|
return sizeof(SHDirectionalLightData);
|
||||||
|
case SH_LIGHT_TYPE::POINT:
|
||||||
|
return 4;
|
||||||
|
case SH_LIGHT_TYPE::SPOT:
|
||||||
|
// TOOD: Change after creating spot light struct
|
||||||
|
return 4;
|
||||||
|
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||||
|
default:
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<SHVkBuffer> SHLightingSubSystem::PerTypeData::GetDataBuffer(void) const noexcept
|
||||||
|
{
|
||||||
|
return dataBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetAlignmentSize(void) const noexcept
|
||||||
|
{
|
||||||
|
return lightDataAlignmentSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetNumLights(void) const noexcept
|
||||||
|
{
|
||||||
|
return numLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SHLightingSubSystem::PerTypeData::GetMaxLights(void) const noexcept
|
||||||
|
{
|
||||||
|
return maxLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
This function takes in a light comp in the event that its data has not
|
||||||
|
been placed in the buffer yet. It also checks if the size of the buffer
|
||||||
|
is big enough to hold the new light. If the buffer is too small, expand
|
||||||
|
it.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component to add.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::AddLight(Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept
|
||||||
|
{
|
||||||
|
if (unboundLight)
|
||||||
|
{
|
||||||
|
// capacity is full
|
||||||
|
if (numLights == maxLights)
|
||||||
|
{
|
||||||
|
// expand first
|
||||||
|
Expand(logicalDevice);
|
||||||
|
|
||||||
|
expanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that the container is big enough, bind the new light
|
||||||
|
|
||||||
|
// Get address of write location
|
||||||
|
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignmentSize * numLights);
|
||||||
|
|
||||||
|
// Write the light data to address
|
||||||
|
WriteLightToAddress(writeLocation, unboundLight);
|
||||||
|
|
||||||
|
// Set the light component to be bound to that location
|
||||||
|
unboundLight->SetBound(numLights);
|
||||||
|
|
||||||
|
// Increase light count
|
||||||
|
++numLights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Modify the data at a specific light address.
|
||||||
|
|
||||||
|
\param lightComp
|
||||||
|
The light component to write.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept
|
||||||
|
{
|
||||||
|
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignmentSize * lightComp->GetIndexInBuffer());
|
||||||
|
WriteLightToAddress(writeLocation, lightComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
if (intermediateData)
|
||||||
|
{
|
||||||
|
// we want to write to the offset of the current frame
|
||||||
|
dataBuffer->WriteToMemory(intermediateData.get(), lightDataAlignmentSize * numLights, 0, lightDataAlignmentSize * maxLights * frameIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Update descriptor sets. We want to call this every time we expand buffers.
|
||||||
|
|
||||||
|
\param binding
|
||||||
|
The binding in the set we want to update.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::UpdateDescSet(uint32_t binding) noexcept
|
||||||
|
{
|
||||||
|
auto buffer = perTypeData[binding].GetDataBuffer();
|
||||||
|
|
||||||
|
// We bind the buffer with the correct desc set binding
|
||||||
|
lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS,
|
||||||
|
binding,
|
||||||
|
{ &buffer, 1 },
|
||||||
|
0,
|
||||||
|
perTypeData[binding].GetAlignmentSize() * perTypeData[binding].GetMaxLights());
|
||||||
|
|
||||||
|
lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Computes dynamic offsets.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::ComputeDynamicOffsets(void) noexcept
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
for (uint32_t j = 0; j < dynamicOffsets.size(); ++j)
|
||||||
|
{
|
||||||
|
auto const& typeData = perTypeData[j];
|
||||||
|
{
|
||||||
|
dynamicOffsets[i][j] = j * typeData.GetAlignmentSize() * typeData.GetMaxLights();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Initializes per light type data. This includes buffers and descriptor
|
||||||
|
sets.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||||
|
{
|
||||||
|
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
||||||
|
|
||||||
|
logicalDevice = device;
|
||||||
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
|
||||||
|
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
||||||
|
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
||||||
|
|
||||||
|
// Create the descriptor set
|
||||||
|
lightingDataDescSet = descPool->Allocate({SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS]}, variableSizes);
|
||||||
|
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
||||||
|
{
|
||||||
|
// initialize all the data first. We add more lights here as we add more types.
|
||||||
|
perTypeData[i].InitializeData(logicalDevice, static_cast<SH_LIGHT_TYPE>(i));
|
||||||
|
UpdateDescSet(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
dynamicOffsets[i].resize(NUM_LIGHT_TYPES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Loops through every single light component and checks for dirty light
|
||||||
|
data. If light data is dirty, rewrite to the CPU container. We also want
|
||||||
|
to bind the descriptor set for the light data.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Run(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||||
|
{
|
||||||
|
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||||
|
bool expanded = false;
|
||||||
|
for (auto& light : lightComps)
|
||||||
|
{
|
||||||
|
auto enumValue = SHUtilities::ToUnderlying(light.GetLightData().type);
|
||||||
|
|
||||||
|
// First we want to make sure the light is already bound to the system. if it
|
||||||
|
// isn't, we write it to the correct buffer.
|
||||||
|
if (!light.GetBound())
|
||||||
|
{
|
||||||
|
perTypeData[enumValue].AddLight(logicalDevice, &light, expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there was modification to the light data
|
||||||
|
if (light.IsDirty())
|
||||||
|
{
|
||||||
|
// Write the data to the CPU
|
||||||
|
perTypeData[enumValue].ModifyLight(&light);
|
||||||
|
|
||||||
|
// Light is now updated in the container
|
||||||
|
light.ClearDirtyFlag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write data to GPU
|
||||||
|
for (auto& data : perTypeData)
|
||||||
|
{
|
||||||
|
data.WriteToGPU(frameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any of the buffers got expanded, the descriptor set is invalid because the expanded buffer
|
||||||
|
// is a new buffer. If some expansion was detected, update descriptor sets.
|
||||||
|
if (expanded)
|
||||||
|
{
|
||||||
|
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
||||||
|
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
|
||||||
|
{
|
||||||
|
UpdateDescSet(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute dynamic offsets. We don't actually have to compute every frame but its pretty lightweight,
|
||||||
|
// so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing.
|
||||||
|
ComputeDynamicOffsets();
|
||||||
|
|
||||||
|
// Bind descriptor set (We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
|
||||||
|
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, {dynamicOffsets[frameIndex]});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Does nothing for now.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void SHLightingSubSystem::Exit(void) noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Resource/SHHandle.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
#include "SHLightData.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHVkLogicalDevice;
|
||||||
|
class SHVkDescriptorPool;
|
||||||
|
class SHVkDescriptorSetGroup;
|
||||||
|
class SHVkDescriptorSetLayout;
|
||||||
|
class SHVkBuffer;
|
||||||
|
class SHLightComponent;
|
||||||
|
class SHVkCommandBuffer;
|
||||||
|
|
||||||
|
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
|
||||||
|
struct SHDirectionalLightData
|
||||||
|
{
|
||||||
|
//! Direction of the light
|
||||||
|
SHVec3 direction;
|
||||||
|
|
||||||
|
//! Represents if the light is active or not
|
||||||
|
uint32_t active;
|
||||||
|
|
||||||
|
//! Each bit in this 32 bit field will represent a layer. If the bit is set,
|
||||||
|
//! when a fragment is being evaluated, the shader will use the fragment's
|
||||||
|
//! layer value to AND with the light's. If result is 1, do lighting calculations.
|
||||||
|
uint32_t cullingMask;
|
||||||
|
|
||||||
|
//! Diffuse color emitted by the light
|
||||||
|
SHVec4 diffuseColor;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SH_API SHLightingSubSystem
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
class PerTypeData
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* STATIC MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static constexpr uint32_t STARTING_NUM_LIGHTS = 20;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER VARIABLES */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
//! Capacity of the container.
|
||||||
|
uint32_t maxLights;
|
||||||
|
|
||||||
|
//! SSBOs need to be aligned. This is to pad lighting structs
|
||||||
|
uint32_t lightDataAlignmentSize;
|
||||||
|
|
||||||
|
//! type of the light. Will be used later when we want to expand
|
||||||
|
SH_LIGHT_TYPE lightType;
|
||||||
|
|
||||||
|
//! number of lights currently alive.
|
||||||
|
uint32_t numLights;
|
||||||
|
|
||||||
|
//! GPU buffer required to store GPU data
|
||||||
|
Handle<SHVkBuffer> dataBuffer;
|
||||||
|
|
||||||
|
//! Before data gets copied to the GPU, it goes into here first. Data here is aligned to whatever struct is
|
||||||
|
//! used to represent data in this container. Note this will store only 1 copy of all the lights, compared
|
||||||
|
//! to the GPU that stores NUM_FRAME_BUFFERS copies.
|
||||||
|
std::unique_ptr<uint8_t[]> intermediateData;
|
||||||
|
|
||||||
|
void WriteLightToAddress (void* address, SHLightComponent* lightComp) noexcept;
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept;
|
||||||
|
void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||||
|
void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept;
|
||||||
|
void ModifyLight (SHLightComponent* lightComp) noexcept;
|
||||||
|
void WriteToGPU (uint32_t frameIndex) noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* GETTERS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static uint32_t GetLightTypeSize (SH_LIGHT_TYPE type) noexcept;
|
||||||
|
Handle<SHVkBuffer> GetDataBuffer (void) const noexcept;
|
||||||
|
uint32_t GetAlignmentSize (void) const noexcept;
|
||||||
|
uint32_t GetNumLights (void) const noexcept;
|
||||||
|
uint32_t GetMaxLights (void) const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//! logical device used for creation
|
||||||
|
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
|
||||||
|
std::array<std::vector<uint32_t>, static_cast<uint32_t>(SHGraphicsConstants::NUM_FRAME_BUFFERS)> dynamicOffsets;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PRIVATE MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void UpdateDescSet (uint32_t binding) noexcept;
|
||||||
|
void ComputeDynamicOffsets (void) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* PUBLIC MEMBER FUNCTIONS */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||||
|
void Run (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||||
|
void Exit (void) noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -142,6 +142,12 @@ namespace SHADE
|
||||||
|
|
||||||
case SHAttribFormat::UINT32_1D:
|
case SHAttribFormat::UINT32_1D:
|
||||||
return std::make_tuple(1, 4, vk::Format::eR32Uint);
|
return std::make_tuple(1, 4, vk::Format::eR32Uint);
|
||||||
|
case SHAttribFormat::UINT32_2D:
|
||||||
|
return std::make_tuple(1, 8, vk::Format::eR32G32Uint);
|
||||||
|
case SHAttribFormat::UINT32_3D:
|
||||||
|
return std::make_tuple(1, 12, vk::Format::eR32G32B32Uint);
|
||||||
|
case SHAttribFormat::UINT32_4D:
|
||||||
|
return std::make_tuple(1, 16, vk::Format::eR32G32B32A32Uint);
|
||||||
}
|
}
|
||||||
return std::make_tuple(0, 0, vk::Format::eR32Sfloat);
|
return std::make_tuple(0, 0, vk::Format::eR32Sfloat);
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,9 @@ namespace SHADE
|
||||||
attDesc.loadOp = vk::AttachmentLoadOp::eLoad;
|
attDesc.loadOp = vk::AttachmentLoadOp::eLoad;
|
||||||
predAttDesc.storeOp = vk::AttachmentStoreOp::eStore;
|
predAttDesc.storeOp = vk::AttachmentStoreOp::eStore;
|
||||||
|
|
||||||
|
attDesc.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
|
||||||
|
attDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore;
|
||||||
|
|
||||||
// TODO: Stencil load and store
|
// TODO: Stencil load and store
|
||||||
|
|
||||||
// When an image is done being used in a renderpass, the image layout will end up being the finalLayout
|
// When an image is done being used in a renderpass, the image layout will end up being the finalLayout
|
||||||
|
|
|
@ -51,6 +51,18 @@ namespace SHADE
|
||||||
case vk::Format::eR32Uint:
|
case vk::Format::eR32Uint:
|
||||||
case vk::Format::eR32Sfloat:
|
case vk::Format::eR32Sfloat:
|
||||||
return 4;
|
return 4;
|
||||||
|
case vk::Format::eR32G32Sint:
|
||||||
|
case vk::Format::eR32G32Uint:
|
||||||
|
case vk::Format::eR32G32Sfloat:
|
||||||
|
return 8;
|
||||||
|
case vk::Format::eR32G32B32Sint:
|
||||||
|
case vk::Format::eR32G32B32Uint:
|
||||||
|
case vk::Format::eR32G32B32Sfloat:
|
||||||
|
return 12;
|
||||||
|
case vk::Format::eR32G32B32A32Sint:
|
||||||
|
case vk::Format::eR32G32B32A32Uint:
|
||||||
|
case vk::Format::eR32G32B32A32Sfloat:
|
||||||
|
return 16;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ namespace SHADE
|
||||||
|
|
||||||
// integer formats
|
// integer formats
|
||||||
UINT32_1D,
|
UINT32_1D,
|
||||||
|
UINT32_2D,
|
||||||
|
UINT32_3D,
|
||||||
|
UINT32_4D,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SHVertexAttribute
|
struct SHVertexAttribute
|
||||||
|
|
|
@ -42,6 +42,15 @@ namespace SHADE
|
||||||
template <IsEnum InputType, IsIntegral OutputType = int>
|
template <IsEnum InputType, IsIntegral OutputType = int>
|
||||||
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
|
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts an enum class member from it's type to the underlying type.
|
||||||
|
* @tparam Enum Restricted to an enum class
|
||||||
|
* @param[in] value A member of the specified enum class.
|
||||||
|
* @returns The value of the enum class member in the output type.
|
||||||
|
*/
|
||||||
|
template<typename Enum>
|
||||||
|
static constexpr typename std::underlying_type_t<Enum> ToUnderlying (Enum value) noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
|
@ -25,4 +25,10 @@ namespace SHADE
|
||||||
return static_cast<OutputType>(enumClassMember);
|
return static_cast<OutputType>(enumClassMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Enum>
|
||||||
|
constexpr typename std::underlying_type_t<Enum> SHUtilities::ToUnderlying(Enum value) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<typename std::underlying_type_t<Enum>>(value);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -0,0 +1,67 @@
|
||||||
|
//#version 450
|
||||||
|
//
|
||||||
|
//layout(local_size_x = 16, local_size_y = 16) in;
|
||||||
|
//layout(set = 4, binding = 0, rgba8) uniform image2D targetImage;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//void main()
|
||||||
|
//{
|
||||||
|
// ivec2 imageSize = imageSize (targetImage);
|
||||||
|
//
|
||||||
|
// if (gl_GlobalInvocationID.x >= imageSize.x && gl_GlobalInvocationID.y >= imageSize.y)
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// // load the image
|
||||||
|
// vec4 color = imageLoad (targetImage, ivec2 (gl_GlobalInvocationID));
|
||||||
|
//
|
||||||
|
// // get the average
|
||||||
|
// float average = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
|
||||||
|
//
|
||||||
|
// // store result into result image
|
||||||
|
// imageStore(targetImage, ivec2(gl_GlobalInvocationID), vec4(average, average, average, 1.0f));
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
/* Start Header *****************************************************************/
|
||||||
|
|
||||||
|
/*! \file (e.g. kirsch.comp)
|
||||||
|
|
||||||
|
\author William Zheng, william.zheng, 60001906. Brandon Mak, brandon.hao 390003920.
|
||||||
|
|
||||||
|
\par william.zheng\@digipen.edu. brandon.hao\@digipen.edu.
|
||||||
|
|
||||||
|
\date Sept 20, 2022
|
||||||
|
|
||||||
|
\brief Copyright (C) 20xx DigiPen Institute of Technology.
|
||||||
|
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. */
|
||||||
|
|
||||||
|
/* End Header *******************************************************************/
|
||||||
|
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
|
||||||
|
layout(local_size_x = 16, local_size_y = 16) in;
|
||||||
|
layout(set = 4, binding = 0, rgba8) uniform image2D inputImage;
|
||||||
|
layout(set = 4, binding = 1, rgba8) uniform image2D targetImage;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// convenient variables
|
||||||
|
ivec2 globalThread = ivec2(gl_GlobalInvocationID);
|
||||||
|
|
||||||
|
vec3 color = imageLoad (inputImage, globalThread).rgb;
|
||||||
|
|
||||||
|
// store result into result image
|
||||||
|
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1.0f));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -23,6 +23,7 @@ layout(location = 2) flat in struct
|
||||||
{
|
{
|
||||||
int materialIndex;
|
int materialIndex;
|
||||||
uint eid;
|
uint eid;
|
||||||
|
uint lightLayerIndex;
|
||||||
} In2;
|
} In2;
|
||||||
|
|
||||||
//layout (set = 0, binding = )
|
//layout (set = 0, binding = )
|
||||||
|
@ -35,6 +36,7 @@ layout (set = 3, binding = 0) buffer MaterialProperties // For materials
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
layout(location = 1) out uint outEntityID;
|
layout(location = 1) out uint outEntityID;
|
||||||
|
layout(location = 2) out uint lightLayerIndices;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
@ -42,5 +44,6 @@ void main()
|
||||||
MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha;
|
MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha;
|
||||||
|
|
||||||
outEntityID = In2.eid;
|
outEntityID = In2.eid;
|
||||||
|
lightLayerIndices = In2.lightLayerIndex;
|
||||||
//outColor = vec4 (1.0f);
|
//outColor = vec4 (1.0f);
|
||||||
}
|
}
|
Binary file not shown.
|
@ -3,12 +3,13 @@
|
||||||
|
|
||||||
//#include "ShaderDescriptorDefinitions.glsl"
|
//#include "ShaderDescriptorDefinitions.glsl"
|
||||||
|
|
||||||
|
|
||||||
layout(location = 0) in vec3 aVertexPos;
|
layout(location = 0) in vec3 aVertexPos;
|
||||||
layout(location = 1) in vec2 aUV;
|
layout(location = 1) in vec2 aUV;
|
||||||
layout(location = 2) in vec3 aNormal;
|
layout(location = 2) in vec3 aNormal;
|
||||||
layout(location = 3) in vec3 aTangent;
|
layout(location = 3) in vec3 aTangent;
|
||||||
layout(location = 4) in mat4 worldTransform;
|
layout(location = 4) in mat4 worldTransform;
|
||||||
layout(location = 8) in uint eid;
|
layout(location = 8) in uvec2 integerData;
|
||||||
|
|
||||||
|
|
||||||
layout(location = 0) out struct
|
layout(location = 0) out struct
|
||||||
|
@ -23,6 +24,7 @@ layout(location = 2) out struct
|
||||||
{
|
{
|
||||||
int materialIndex;
|
int materialIndex;
|
||||||
uint eid;
|
uint eid;
|
||||||
|
uint lightLayerIndex;
|
||||||
|
|
||||||
} Out2;
|
} Out2;
|
||||||
|
|
||||||
|
@ -36,7 +38,8 @@ void main()
|
||||||
{
|
{
|
||||||
Out.uv = aUV;
|
Out.uv = aUV;
|
||||||
Out2.materialIndex = gl_InstanceIndex;
|
Out2.materialIndex = gl_InstanceIndex;
|
||||||
Out2.eid = eid;
|
Out2.eid = integerData[0];
|
||||||
|
Out2.lightLayerIndex = integerData[1];
|
||||||
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
||||||
Out.vertColor = vec4 (aVertexPos, 1.0f);
|
Out.vertColor = vec4 (aVertexPos, 1.0f);
|
||||||
}
|
}
|
Binary file not shown.
Loading…
Reference in New Issue