Merge remote-tracking branch 'origin/SP3-1-Rendering' into SP3-1-Rendering
This commit is contained in:
commit
32278e1564
|
@ -22,6 +22,8 @@
|
|||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Math/Transform/SHTransformSystem.h"
|
||||
|
||||
#include "Scenes/SBTestScene.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
||||
|
@ -45,8 +47,10 @@ namespace Sandbox
|
|||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
||||
|
||||
// Create Systems
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHScriptEngine>();
|
||||
// TODO(Diren): Create Physics System here
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
|
||||
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
|
||||
|
||||
// Create Routines
|
||||
|
@ -54,6 +58,12 @@ namespace Sandbox
|
|||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::UpdateRoutine>();
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::LateUpdateRoutine>();
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameCleanUpRoutine>();
|
||||
|
||||
// TODO(Diren): Register Physics System & Routines here
|
||||
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHTransformSystem, SHADE::SHTransformSystem::TransformUpdateRoutine>();
|
||||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
|
||||
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BatcherDispatcherRoutine>();
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>();
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>();
|
||||
|
|
|
@ -38,35 +38,56 @@ namespace Sandbox
|
|||
// Create Materials
|
||||
auto matInst = graphicsSystem->AddMaterialInstance();
|
||||
|
||||
// Create entity and add mesh
|
||||
testObj = SHADE::SHEntityManager::CreateEntity<SHADE::SHRenderable, SHTransformComponent>();
|
||||
//SHComponentManager::AddComponent<SHTransformComponent>(testObj);
|
||||
auto& renderable = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHRenderable>(testObj);
|
||||
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
|
||||
// Create Stress Test Objects
|
||||
static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f };
|
||||
constexpr int NUM_ROWS = 200;
|
||||
constexpr int NUM_COLS = 100;
|
||||
static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f };
|
||||
static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f };
|
||||
for (int z = 0; z < NUM_ROWS; ++z)
|
||||
for (int x = 0; x < NUM_COLS; ++x)
|
||||
{
|
||||
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
|
||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
|
||||
|
||||
renderable.Mesh = CUBE_MESH;
|
||||
renderable.SetMaterial(matInst);
|
||||
renderable.TransformMatrix.Translate(0.0f, 0.0f, 2.0f);
|
||||
|
||||
// Add script
|
||||
renderable.Mesh = CUBE_MESH;
|
||||
renderable.SetMaterial(matInst);
|
||||
|
||||
// Set initial positions
|
||||
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, 0.0f, z * TEST_OBJ_SPACING.z });
|
||||
//transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
|
||||
stressTestObjects.emplace_back(entity);
|
||||
}
|
||||
|
||||
// Create blank entity with a script
|
||||
testObj = SHADE::SHEntityManager::CreateEntity();
|
||||
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
|
||||
scriptEngine->AddScript(*SHADE::SHEntityManager::GetEntityByID(testObj), "TestScript");
|
||||
scriptEngine->AddScript(testObj, "TestScript");
|
||||
}
|
||||
|
||||
void SBTestScene::Update(float dt)
|
||||
{
|
||||
static float rotation = 0.0f;
|
||||
/*static float rotation = 0.0f;
|
||||
|
||||
auto& renderable = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHRenderable>(testObj);
|
||||
SHTransform tf;
|
||||
tf.rotation = SHVec3(rotation, 0.0f, 0.0f);
|
||||
renderable.TransformMatrix = tf.ComputeTRS();
|
||||
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
|
||||
|
||||
rotation += dt * 10.0f;
|
||||
transform.SetLocalRotation(rotation, 0.0f, 0.0f);
|
||||
rotation += dt * 10.0f;*/
|
||||
/*static float rotation = 0.0f;
|
||||
|
||||
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(stressTestObjects[0]);
|
||||
|
||||
transform.SetWorldPosition({rotation, 0.0f, 0.0f});
|
||||
rotation += dt * 10.0f;*/
|
||||
|
||||
// Destroy entity if space is pressed
|
||||
if (GetKeyState(VK_SPACE) & 0x8000)
|
||||
SHADE::SHEntityManager::DestroyEntity(testObj);
|
||||
{
|
||||
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
|
||||
scriptEngine->RemoveAllScripts(testObj);
|
||||
}
|
||||
}
|
||||
|
||||
void SBTestScene::Render()
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Sandbox
|
|||
private:
|
||||
EntityID camera;
|
||||
EntityID testObj;
|
||||
std::vector<EntityID> stressTestObjects;
|
||||
|
||||
public:
|
||||
virtual void Load();
|
||||
|
|
|
@ -22,6 +22,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/Pipeline/SHVkPipeline.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -33,6 +35,9 @@ namespace SHADE
|
|||
{
|
||||
if (!pipeline)
|
||||
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
||||
|
||||
// Mark all as dirty
|
||||
setAllDirtyFlags();
|
||||
}
|
||||
|
||||
void SHBatch::Add(const SHRenderable* renderable)
|
||||
|
@ -52,6 +57,9 @@ namespace SHADE
|
|||
|
||||
// Add renderable in
|
||||
subBatch->Renderables.insert(renderable);
|
||||
|
||||
// Mark all as dirty
|
||||
setAllDirtyFlags();
|
||||
}
|
||||
|
||||
void SHBatch::Remove(const SHRenderable* renderable)
|
||||
|
@ -67,6 +75,10 @@ namespace SHADE
|
|||
return;
|
||||
|
||||
subBatch->Renderables.erase(renderable);
|
||||
|
||||
// Mark all as dirty
|
||||
for (bool& dirt : isDirty)
|
||||
dirt = true;
|
||||
}
|
||||
|
||||
void SHBatch::Clear()
|
||||
|
@ -81,13 +93,22 @@ namespace SHADE
|
|||
|
||||
|
||||
// Clear GPU buffers
|
||||
drawDataBuffer.Free();
|
||||
transformDataBuffer.Free();
|
||||
matPropsBuffer.Free();
|
||||
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||
{
|
||||
drawDataBuffer[i].Free();
|
||||
transformDataBuffer[i].Free();
|
||||
matPropsBuffer[i].Free();
|
||||
}
|
||||
}
|
||||
|
||||
void SHBatch::UpdateTransformBuffer()
|
||||
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;
|
||||
}
|
||||
|
||||
// Reset Transform Data
|
||||
transformData.clear();
|
||||
|
||||
|
@ -96,17 +117,32 @@ namespace SHADE
|
|||
for (const SHRenderable* renderable : subBatch.Renderables)
|
||||
{
|
||||
// Transform
|
||||
transformData.emplace_back(renderable->TransformMatrix);
|
||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(renderable->GetEID());
|
||||
if (!transform)
|
||||
{
|
||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||
transformData.emplace_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
transformData.emplace_back(transform->GetTRS());
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer to GPU
|
||||
transformDataBuffer->WriteToMemory(transformData.data(), transformData.size() * sizeof(SHMatrix), 0, 0);
|
||||
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), transformData.size() * sizeof(SHMatrix), 0, 0);
|
||||
}
|
||||
|
||||
void SHBatch::Build(Handle<SHVkLogicalDevice> device)
|
||||
void SHBatch::Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
{
|
||||
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to build as there are no changes
|
||||
if (!isDirty)
|
||||
if (!isDirty[frameIndex])
|
||||
return;
|
||||
|
||||
// Count number of elements
|
||||
|
@ -116,61 +152,77 @@ namespace SHADE
|
|||
numTotalElements += subBatch.Renderables.size();
|
||||
}
|
||||
|
||||
// Generate CPU buffers
|
||||
// - Draw data
|
||||
drawData.reserve(subBatches.size());
|
||||
drawData.clear();
|
||||
// - Transform data
|
||||
transformData.reserve(numTotalElements);
|
||||
transformData.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 singleMatPropSize = 0;
|
||||
Byte matPropTotalBytes = 0;
|
||||
if (!EMPTY_MAT_PROPS)
|
||||
// Generate CPU buffers if there are changes
|
||||
if (isCPUBuffersDirty)
|
||||
{
|
||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||
matPropTotalBytes = drawData.size() * singleMatPropSize;
|
||||
if (matPropsDataSize < matPropTotalBytes)
|
||||
// - Draw data
|
||||
drawData.reserve(subBatches.size());
|
||||
drawData.clear();
|
||||
// - Transform data
|
||||
transformData.reserve(numTotalElements);
|
||||
transformData.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 singleMatPropSize = 0;
|
||||
Byte matPropTotalBytes = 0;
|
||||
if (!EMPTY_MAT_PROPS)
|
||||
{
|
||||
matPropsData.reset(new char[matPropTotalBytes]);
|
||||
matPropsDataSize = matPropTotalBytes;
|
||||
}
|
||||
}
|
||||
|
||||
// Build Sub Batches
|
||||
uint32_t nextInstanceIndex = 0;
|
||||
char* propsCurrPtr = matPropsData.get();
|
||||
for (auto& subBatch : subBatches)
|
||||
{
|
||||
// Create command
|
||||
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
||||
{
|
||||
.indexCount = subBatch.Mesh->IndexCount,
|
||||
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
|
||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||
.firstInstance = nextInstanceIndex
|
||||
});
|
||||
|
||||
// Fill in buffers (CPU)
|
||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
||||
{
|
||||
// Transform
|
||||
transformData.emplace_back(renderable->TransformMatrix);
|
||||
// Material Properties
|
||||
if (!EMPTY_MAT_PROPS)
|
||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||
matPropTotalBytes = drawData.size() * singleMatPropSize;
|
||||
if (matPropsDataSize < matPropTotalBytes)
|
||||
{
|
||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||
propsCurrPtr += singleMatPropSize;
|
||||
matPropsData.reset(new char[matPropTotalBytes]);
|
||||
matPropsDataSize = matPropTotalBytes;
|
||||
}
|
||||
}
|
||||
|
||||
// Build Sub Batches
|
||||
uint32_t nextInstanceIndex = 0;
|
||||
char* propsCurrPtr = matPropsData.get();
|
||||
for (auto& subBatch : subBatches)
|
||||
{
|
||||
// Create command
|
||||
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
||||
{
|
||||
.indexCount = subBatch.Mesh->IndexCount,
|
||||
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
|
||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||
.firstInstance = nextInstanceIndex
|
||||
});
|
||||
|
||||
// Fill in buffers (CPU)
|
||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
||||
{
|
||||
// Transform
|
||||
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(renderable->GetEID());
|
||||
if (!transform)
|
||||
{
|
||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||
transformData.emplace_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
transformData.emplace_back(transform->GetTRS());
|
||||
}
|
||||
|
||||
// Material Properties
|
||||
if (!EMPTY_MAT_PROPS)
|
||||
{
|
||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||
propsCurrPtr += singleMatPropSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Successfully update CPU buffers
|
||||
isCPUBuffersDirty = false;
|
||||
}
|
||||
|
||||
// Send all buffered data to the GPU buffers
|
||||
|
@ -179,36 +231,52 @@ namespace SHADE
|
|||
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
device, drawDataBuffer, drawData.data(), DRAW_DATA_BYTES,
|
||||
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, transformData.data(), TF_DATA_BYTES,
|
||||
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
||||
BuffUsage::eVertexBuffer
|
||||
);
|
||||
// - Material Properties Buffer
|
||||
if (!EMPTY_MAT_PROPS)
|
||||
if (matPropsData)
|
||||
{
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
device, matPropsBuffer, matPropsData.get(), static_cast<uint32_t>(matPropTotalBytes),
|
||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||
BuffUsage::eStorageBuffer
|
||||
);
|
||||
}
|
||||
|
||||
isDirty = false;
|
||||
isDirty[frameIndex] = false;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SHBatch - Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer)
|
||||
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;
|
||||
}
|
||||
|
||||
cmdBuffer->BindPipeline(pipeline);
|
||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer, 0);
|
||||
cmdBuffer->DrawMultiIndirect(drawDataBuffer, static_cast<uint32_t>(drawData.size()));
|
||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SHBatch - Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHBatch::setAllDirtyFlags()
|
||||
{
|
||||
for (bool& dirt : isDirty)
|
||||
dirt = true;
|
||||
isCPUBuffersDirty = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,14 @@ of DigiPen Institute of Technology is prohibited.
|
|||
|
||||
// STL Includes
|
||||
#include <unordered_set>
|
||||
#include <array>
|
||||
// External Dependencies
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
// Project Includes
|
||||
#include "Resource/Handle.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -71,9 +73,9 @@ namespace SHADE
|
|||
void Add(const SHRenderable* renderable);
|
||||
void Remove(const SHRenderable* renderable);
|
||||
void Clear();
|
||||
void UpdateTransformBuffer();
|
||||
void Build(Handle<SHVkLogicalDevice> device);
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer);
|
||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
@ -88,15 +90,21 @@ namespace SHADE
|
|||
Handle<SHVkPipeline> pipeline;
|
||||
// Batch Tree
|
||||
std::vector<SHSubBatch> subBatches;
|
||||
bool isDirty = true;
|
||||
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty;
|
||||
// CPU Buffers
|
||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||
std::vector<SHMatrix> transformData;
|
||||
std::unique_ptr<char> matPropsData;
|
||||
Byte matPropsDataSize = 0;
|
||||
bool isCPUBuffersDirty = true;
|
||||
// GPU Buffers
|
||||
Handle<SHVkBuffer> drawDataBuffer;
|
||||
Handle<SHVkBuffer> transformDataBuffer;
|
||||
Handle<SHVkBuffer> matPropsBuffer;
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer;
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> transformDataBuffer;
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> matPropsBuffer;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void setAllDirtyFlags();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -91,12 +91,12 @@ namespace SHADE
|
|||
(*superBatch)->Remove(renderable);
|
||||
}
|
||||
|
||||
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device)
|
||||
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex)
|
||||
{
|
||||
// Build SuperBatches
|
||||
for (auto& batch : superBatches)
|
||||
{
|
||||
batch->Build(device);
|
||||
batch->Build(device, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,11 +109,11 @@ namespace SHADE
|
|||
superBatches.clear();
|
||||
}
|
||||
|
||||
void SHBatcher::UpdateTransformBuffer()
|
||||
{
|
||||
void SHBatcher::UpdateTransformBuffer(uint32_t frameIndex)
|
||||
{
|
||||
for (auto& batch : superBatches)
|
||||
{
|
||||
batch->UpdateTransformBuffer();
|
||||
batch->UpdateTransformBuffer(frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,9 +51,9 @@ namespace SHADE
|
|||
void PrepareBatches();
|
||||
void AddToBatch(SHRenderable const* renderable);
|
||||
void RemoveFromBatch(SHRenderable const* renderable);
|
||||
void FinaliseBatches(Handle<SHVkLogicalDevice> device);
|
||||
void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
|
||||
void ClearBatches();
|
||||
void UpdateTransformBuffer();
|
||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void RegisterSuperBatch(Handle<SHSuperBatch> superBatch);
|
||||
void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch);
|
||||
|
||||
|
|
|
@ -78,29 +78,29 @@ namespace SHADE
|
|||
batches.clear();
|
||||
}
|
||||
|
||||
void SHSuperBatch::UpdateTransformBuffer()
|
||||
void SHSuperBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
||||
{
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.UpdateTransformBuffer();
|
||||
batch.UpdateTransformBuffer(frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device) noexcept
|
||||
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept
|
||||
{
|
||||
// Build all batches
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.Build(device);
|
||||
batch.Build(device, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
||||
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
// Build all batches
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.Draw(cmdBuffer);
|
||||
batch.Draw(cmdBuffer, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ namespace SHADE
|
|||
void Add(const SHRenderable* renderable) noexcept;
|
||||
void Remove(const SHRenderable* renderable) noexcept;
|
||||
void Clear() noexcept;
|
||||
void UpdateTransformBuffer();
|
||||
void Build(Handle<SHVkLogicalDevice> device) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
|
|
@ -22,24 +22,24 @@ namespace SHADE
|
|||
void SHCamera::SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up)
|
||||
{
|
||||
SHVec3 view = target - pos; view = SHVec3::Normalise(view);
|
||||
SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right);
|
||||
const SHVec3 UP = SHVec3::Cross(right, view);
|
||||
|
||||
viewMatrix = SHMatrix::Identity;
|
||||
viewMatrix(0, 0) = UP[0];
|
||||
viewMatrix(1, 0) = UP[1];
|
||||
viewMatrix(2, 0) = UP[2];
|
||||
viewMatrix(0, 1) = right[0];
|
||||
viewMatrix(1, 1) = right[1];
|
||||
viewMatrix(2, 1) = right[2];
|
||||
viewMatrix(0, 2) = view[0];
|
||||
viewMatrix(1, 2) = view[1];
|
||||
viewMatrix(2, 2) = view[2];
|
||||
viewMatrix(3, 0) = -UP.Dot(pos);
|
||||
viewMatrix(3, 1) = -right.Dot(pos);
|
||||
viewMatrix(3, 2) = -view.Dot(pos);
|
||||
|
||||
isDirty = true;
|
||||
SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right);
|
||||
const SHVec3 UP = SHVec3::Cross(right, view);
|
||||
|
||||
viewMatrix = SHMatrix::Identity;
|
||||
viewMatrix(0, 0) = UP[0];
|
||||
viewMatrix(1, 0) = UP[1];
|
||||
viewMatrix(2, 0) = UP[2];
|
||||
viewMatrix(0, 1) = right[0];
|
||||
viewMatrix(1, 1) = right[1];
|
||||
viewMatrix(2, 1) = right[2];
|
||||
viewMatrix(0, 2) = view[0];
|
||||
viewMatrix(1, 2) = view[1];
|
||||
viewMatrix(2, 2) = view[2];
|
||||
viewMatrix(3, 0) = -UP.Dot(pos);
|
||||
viewMatrix(3, 1) = -right.Dot(pos);
|
||||
viewMatrix(3, 2) = -view.Dot(pos);
|
||||
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -114,7 +114,8 @@ namespace SHADE
|
|||
screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f);
|
||||
worldCamera = resourceManager.Create<SHCamera>();
|
||||
worldCamera->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
//worldCamera->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
worldCamera->SetLookAt(SHVec3(0.0f, 5.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
|
||||
|
||||
// Create Default Viewport
|
||||
|
@ -306,7 +307,7 @@ namespace SHADE
|
|||
for (auto vp : viewports)
|
||||
for (auto renderer : vp->GetRenderers())
|
||||
{
|
||||
renderer->GetRenderGraph()->FinaliseBatch();
|
||||
renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame());
|
||||
}
|
||||
|
||||
// Resize
|
||||
|
|
|
@ -92,5 +92,4 @@ namespace SHADE
|
|||
materialChanged = false;
|
||||
oldMaterial = {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@ namespace SHADE
|
|||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
Handle<SHMesh> Mesh;
|
||||
SHMatrix TransformMatrix; // TODO: Replace with Transform component
|
||||
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -346,13 +346,13 @@ namespace SHADE
|
|||
inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
|
||||
}
|
||||
|
||||
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer) noexcept
|
||||
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
// Ensure correct transforms are provided
|
||||
superBatch->UpdateTransformBuffer();
|
||||
superBatch->UpdateTransformBuffer(frameIndex);
|
||||
|
||||
// Draw all the batches
|
||||
superBatch->Draw(commandBuffer);
|
||||
superBatch->Draw(commandBuffer, frameIndex);
|
||||
|
||||
// Draw all the exterior draw calls
|
||||
for (auto& drawCall : exteriorDrawCalls)
|
||||
|
@ -591,7 +591,7 @@ namespace SHADE
|
|||
|
||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||
{
|
||||
subpasses[i]->Execute(commandBuffer);
|
||||
subpasses[i]->Execute(commandBuffer, frameIndex);
|
||||
|
||||
// Go to next subpass if not last subpass
|
||||
if (i != subpasses.size() - 1)
|
||||
|
@ -624,14 +624,9 @@ namespace SHADE
|
|||
return pipeline;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::FinaliseBatch()
|
||||
{
|
||||
batcher.FinaliseBatches(logicalDeviceHdl);
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::UpdateBatchTransforms()
|
||||
{
|
||||
batcher.UpdateTransformBuffer();
|
||||
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex)
|
||||
{
|
||||
batcher.FinaliseBatches(logicalDeviceHdl, frameIndex);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -1088,11 +1083,11 @@ namespace SHADE
|
|||
node->Execute(cmdBuffer, frameIndex);
|
||||
}
|
||||
|
||||
void SHRenderGraph::FinaliseBatch()
|
||||
{
|
||||
void SHRenderGraph::FinaliseBatch(uint32_t frameIndex)
|
||||
{
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
node->FinaliseBatch();
|
||||
node->FinaliseBatch(frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ namespace SHADE
|
|||
void AddInput(std::string resourceToReference) noexcept;
|
||||
|
||||
// Runtime functions
|
||||
void Execute(Handle<SHVkCommandBuffer>& commandBuffer) noexcept;
|
||||
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
|
||||
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -230,8 +230,7 @@ namespace SHADE
|
|||
// TODO: RemoveSubpass()
|
||||
void Execute (Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
|
||||
Handle<SHVkPipeline> GetOrCreatePipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
||||
void FinaliseBatch();
|
||||
void UpdateBatchTransforms();
|
||||
void FinaliseBatch(uint32_t frameIndex);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
|
@ -289,7 +288,7 @@ namespace SHADE
|
|||
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept;
|
||||
void Generate (void) noexcept;
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
void FinaliseBatch();
|
||||
void FinaliseBatch(uint32_t frameIndex);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
|
|
|
@ -25,14 +25,12 @@ namespace SHADE
|
|||
/* Static Data Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
//SHTransformSystem::TransformUpdateRoutine SHTransformSystem::UpdateRoutine;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine()
|
||||
: SHSystemRoutine { "Transform Update", false }
|
||||
: SHSystemRoutine { "Transform Update", true }
|
||||
{}
|
||||
|
||||
|
||||
|
@ -47,6 +45,16 @@ namespace SHADE
|
|||
UpdateEntity(SCENE_GRAPH.GetRoot());
|
||||
}
|
||||
|
||||
void SHTransformSystem::Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SHTransformSystem::Exit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -58,19 +66,8 @@ namespace SHADE
|
|||
|
||||
for (const auto* child : node->GetChildren())
|
||||
{
|
||||
// Active states of entities should sync with scene nodes
|
||||
const bool IS_NODE_ACTIVE = child->IsActive();
|
||||
|
||||
#ifdef _DEBUG
|
||||
const bool IS_ENTITY_ACTIVE = SHEntityManager::GetEntityByID(child->GetEntityID())->GetActive();
|
||||
SHASSERT(IS_NODE_ACTIVE == IS_ENTITY_ACTIVE, "Entity and Node active states are not synced!")
|
||||
#endif
|
||||
|
||||
if (!IS_NODE_ACTIVE)
|
||||
{
|
||||
UpdateEntity(child);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const bool HAS_TRANSFORM = SHComponentManager::HasComponent<SHTransformComponent>(child->GetEntityID());
|
||||
if (!HAS_TRANSFORM)
|
||||
|
@ -78,8 +75,13 @@ namespace SHADE
|
|||
|
||||
auto* childTransform = SHComponentManager::GetComponent<SHTransformComponent>(child->GetEntityID());
|
||||
|
||||
if (childTransform->dirty || HAS_PARENT_CHANGED)
|
||||
UpdateTransform(*childTransform, NODE_TRANSFORM);
|
||||
// Only update if node in hierarchy and component are both active
|
||||
const bool IS_NODE_ACTIVE = child->IsActive();
|
||||
if (IS_NODE_ACTIVE && childTransform->isActive)
|
||||
{
|
||||
if (childTransform->dirty || HAS_PARENT_CHANGED)
|
||||
UpdateTransform(*childTransform, NODE_TRANSFORM);
|
||||
}
|
||||
|
||||
UpdateEntity(child);
|
||||
|
||||
|
@ -96,7 +98,7 @@ namespace SHADE
|
|||
if (parent)
|
||||
{
|
||||
localToWorld = parent->GetTRS();
|
||||
worldToLocal = SHMatrix::Inverse(tf.local.trs);
|
||||
worldToLocal = SHMatrix::Inverse(localToWorld);
|
||||
}
|
||||
|
||||
while (!tf.updateQueue.empty())
|
||||
|
@ -140,6 +142,10 @@ namespace SHADE
|
|||
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
|
||||
|
||||
tf.world.ComputeTRS();
|
||||
|
||||
// Transpose TRS to column major
|
||||
tf.local.trs.Transpose();
|
||||
tf.world.trs.Transpose();
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -21,7 +21,7 @@ namespace SHADE
|
|||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHTransformSystem : public SHSystem
|
||||
class SH_API SHTransformSystem final : public SHSystem
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -29,7 +29,7 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHTransformSystem () = default;
|
||||
~SHTransformSystem () = default;
|
||||
~SHTransformSystem () override = default;
|
||||
|
||||
SHTransformSystem (const SHTransformSystem&) = delete;
|
||||
SHTransformSystem (SHTransformSystem&&) = delete;
|
||||
|
@ -45,7 +45,7 @@ namespace SHADE
|
|||
/* System Routines */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
class TransformUpdateRoutine : public SHSystemRoutine
|
||||
class SH_API TransformUpdateRoutine final: public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
@ -72,7 +72,12 @@ namespace SHADE
|
|||
void Execute(double dt) noexcept override;
|
||||
};
|
||||
|
||||
//static TransformUpdateRoutine UpdateRoutine;
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void Init () override;
|
||||
void Exit () override;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -497,9 +497,16 @@ namespace SHADE
|
|||
SHSceneNode* newNode = AllocateNode(entityID);
|
||||
|
||||
if (parent == nullptr)
|
||||
{
|
||||
// Specific handling for root to avoid a warning when removing a non-existent child
|
||||
parent = root;
|
||||
|
||||
newNode->SetParent(parent);
|
||||
newNode->parent = root;
|
||||
root->children.emplace_back(newNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
newNode->SetParent(parent);
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
|
|
@ -103,17 +103,17 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Script Manipulation Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
bool SHScriptEngine::AddScript(const SHEntity& entity, const std::string_view& scriptName)
|
||||
bool SHScriptEngine::AddScript(EntityID entity, const std::string_view& scriptName)
|
||||
{
|
||||
return csScriptsAdd(entity.GetEID(), scriptName.data());
|
||||
return csScriptsAdd(entity, scriptName.data());
|
||||
}
|
||||
void SHScriptEngine::RemoveAllScripts(const SHEntity& entity)
|
||||
void SHScriptEngine::RemoveAllScripts(EntityID entity)
|
||||
{
|
||||
csScriptsRemoveAll(entity.GetEID());
|
||||
csScriptsRemoveAll(entity);
|
||||
}
|
||||
void SHScriptEngine::RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy)
|
||||
void SHScriptEngine::RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy)
|
||||
{
|
||||
csScriptsRemoveAllImmediately(entity.GetEID(), callOnDestroy);
|
||||
csScriptsRemoveAllImmediately(entity, callOnDestroy);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -116,14 +116,14 @@ namespace SHADE
|
|||
/// True if successfully added. False otherwise with the error logged to the
|
||||
/// console.
|
||||
/// </returns>
|
||||
bool AddScript(const SHEntity& entity, const std::string_view& scriptName);
|
||||
bool AddScript(EntityID entity, const std::string_view& scriptName);
|
||||
/// <summary>
|
||||
/// Removes all Scripts attached to the specified Entity. Does not do anything
|
||||
/// if the specified Entity is invalid or does not have any Scripts
|
||||
/// attached.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity to remove the scripts from.</param>
|
||||
void RemoveAllScripts(const SHEntity& entity);
|
||||
void RemoveAllScripts(EntityID entity);
|
||||
/// <summary>
|
||||
/// Removes all Scripts attached to the specified Entity. Unlike
|
||||
/// RemoveAllScripts(), this removes all the scripts immediately.
|
||||
|
@ -135,7 +135,7 @@ namespace SHADE
|
|||
/// Whether or not to call OnDestroy on the scripts. This is ignored if not in
|
||||
/// play mode.
|
||||
/// </param>
|
||||
void RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy);
|
||||
void RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Script Serialisation Functions */
|
||||
|
|
Loading…
Reference in New Issue