Merge branch 'main' into SP3-13-Assets-Manager

This commit is contained in:
Xiao Qi 2022-10-23 17:08:37 +08:00
commit 4019b4914c
51 changed files with 2578 additions and 373 deletions

View File

@ -0,0 +1,54 @@
[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=387,918
Collapsed=0
DockId=0x00000004,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=387,92
Collapsed=0
DockId=0x00000003,0
[Window][Viewport]
Pos=648,48
Size=2519,1319
Collapsed=0
DockId=0x00000002,0
[Window][ Viewport]
Pos=389,48
Size=1258,1012
Collapsed=0
DockId=0x00000002,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=387,1036 Split=Y Selected=0x1E6EB881
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252

View File

@ -93,6 +93,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>(); SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
#ifdef SHEDITOR #ifdef SHEDITOR
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>(); SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();

View File

@ -14,6 +14,7 @@
#include "Physics/Components/SHColliderComponent.h" #include "Physics/Components/SHColliderComponent.h"
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Camera/SHCameraComponent.h"
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
using namespace SHADE; using namespace SHADE;
@ -155,6 +156,10 @@ namespace Sandbox
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f }); transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f }); transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase"); scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
SHComponentManager::AddComponent<SHCameraComponent>(0);
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
} }
void SBTestScene::Update(float dt) void SBTestScene::Update(float dt)

View File

@ -1,7 +1,9 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHCameraComponent.h" #include "SHCameraComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "SHCameraSystem.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE namespace SHADE
{ {
@ -22,33 +24,69 @@ namespace SHADE
void SHCameraComponent::SetYaw(float yaw) noexcept void SHCameraComponent::SetYaw(float yaw) noexcept
{ {
this->yaw = yaw; this->yaw = yaw;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{rotation.x,yaw, rotation.z});
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPitch(float pitch) noexcept void SHCameraComponent::SetPitch(float pitch) noexcept
{ {
this->pitch = pitch; this->pitch = pitch;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{ pitch,rotation.y, rotation.z });
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetRoll(float roll) noexcept void SHCameraComponent::SetRoll(float roll) noexcept
{ {
this->roll = roll; this->roll = roll;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 rotation = transform->GetWorldRotation();
transform->SetWorldRotation(SHVec3{ rotation.x,rotation.y, roll});
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPositionX(float x) noexcept void SHCameraComponent::SetPositionX(float x) noexcept
{ {
position.x = x; position.x = x;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ x,position.y, position.z});
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPositionY(float y) noexcept void SHCameraComponent::SetPositionY(float y) noexcept
{ {
position.y = y; position.y = y;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ position.x,y, position.z });
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPositionZ(float z) noexcept void SHCameraComponent::SetPositionZ(float z) noexcept
{ {
position.z = z; position.z = z;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ position.x,position.y, z });
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPosition(float x,float y, float z) noexcept void SHCameraComponent::SetPosition(float x,float y, float z) noexcept
@ -56,11 +94,23 @@ namespace SHADE
position.x = x; position.x = x;
position.y = y; position.y = y;
position.z = z; position.z = z;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(SHVec3{ x,y, z });
}
dirtyView = true; dirtyView = true;
} }
void SHCameraComponent::SetPosition(SHVec3& pos) noexcept void SHCameraComponent::SetPosition(SHVec3& pos) noexcept
{ {
this->position = pos; this->position = pos;
if (SHComponentManager::HasComponent<SHTransformComponent>(GetEID()))
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
SHVec3 position = transform->GetWorldPosition();
transform->SetWorldRotation(pos);
}
dirtyView = true; dirtyView = true;
} }
@ -128,4 +178,12 @@ namespace SHADE
return projMatrix; return projMatrix;
} }
void SHCameraComponent::SetMainCamera(size_t directorCameraIndex) noexcept
{
auto system = SHSystemManager::GetSystem<SHCameraSystem>();
system->GetDirector(directorCameraIndex)->SetMainCamera(*this);
}
} }

View File

@ -70,6 +70,8 @@ namespace SHADE
const SHMatrix& GetViewMatrix() const noexcept; const SHMatrix& GetViewMatrix() const noexcept;
const SHMatrix& GetProjMatrix() const noexcept; const SHMatrix& GetProjMatrix() const noexcept;
void SetMainCamera(size_t cameraDirectorIndex = 0) noexcept;
float movementSpeed; float movementSpeed;
SHVec3 turnSpeed; SHVec3 turnSpeed;

View File

@ -0,0 +1,65 @@
#include "SHpch.h"
#include "SHCameraDirector.h"
#include "SHCameraComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/SHECSMacros.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Tools/SHLog.h"
namespace SHADE
{
SHCameraDirector::SHCameraDirector()
:mainCameraEID(MAX_EID), transitionCameraEID(MAX_EID)
{
}
SHMatrix SHCameraDirector::GetViewMatrix() const noexcept
{
return viewMatrix;
}
SHMatrix SHCameraDirector::GetProjMatrix() const noexcept
{
return projMatrix;
}
SHMatrix SHCameraDirector::GetVPMatrix() const noexcept
{
return projMatrix * viewMatrix;
}
void SHCameraDirector::UpdateMatrix() noexcept
{
if (mainCameraEID == MAX_EID)
{
auto& dense = SHComponentManager::GetDense<SHCameraComponent>();
if (dense.size() == 0)
{
return;
}
mainCameraEID = dense[0].GetEID();
}
SHCameraComponent* camComponent = SHComponentManager::GetComponent_s<SHCameraComponent>(mainCameraEID);
if (!camComponent)
{
SHLOG_WARNING("Camera Director warning: Entity does not have a camera");
}
else
{
viewMatrix = camComponent->GetViewMatrix();
projMatrix = camComponent->GetProjMatrix();
}
}
void SHCameraDirector::SetMainCamera(SHCameraComponent& camera) noexcept
{
if (SHEntityManager::IsValidEID(camera.GetEID()) == false)
{
SHLOG_WARNING("Camera Director Warning: Attempting to set an invalid entity as main camera.")
return;
}
mainCameraEID = camera.GetEID();
}
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "SH_API.h"
#include "ECS_Base/Entity/SHEntity.h"
#include "Math/SHMatrix.h"
#include "Resource/SHHandle.h"
namespace SHADE
{
class SHCameraComponent;
class SH_API SHCameraDirector
{
public:
SHCameraDirector();
~SHCameraDirector() = default;
EntityID mainCameraEID;
EntityID transitionCameraEID;
SHMatrix GetViewMatrix() const noexcept;
SHMatrix GetProjMatrix() const noexcept;
SHMatrix GetVPMatrix() const noexcept;
void UpdateMatrix() noexcept;
void SetMainCamera(SHCameraComponent& cam) noexcept;
private:
protected:
SHMatrix viewMatrix;
SHMatrix projMatrix;
};
typedef Handle<SHCameraDirector> DirectorHandle;
}

View File

@ -3,12 +3,63 @@
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Input/SHInputManager.h" #include "Input/SHInputManager.h"
#include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec2.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE namespace SHADE
{ {
void SHCameraSystem::UpdateEditorCamera(double dt) noexcept
{
auto& camera = editorCamera;
SHVec3 view, right, UP;
GetCameraAxis(camera, view, right, UP);
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
{
camera.position -= right * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::D))
{
camera.position += right * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::W))
{
camera.position += view * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::S))
{
camera.position -= view * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::Q))
{
camera.position += UP * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::E))
{
camera.position -= UP * dt * camera.movementSpeed;
camera.dirtyView = true;
}
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::RMB))
{
double mouseX, mouseY;
SHInputManager::GetMouseVelocity(&mouseX, &mouseY);
//std::cout << camera.yaw << std::endl;
camera.pitch -= mouseY * dt * camera.turnSpeed.x;
camera.yaw -= mouseX * dt * camera.turnSpeed.y;
camera.dirtyView = true;
}
UpdateCameraComponent(editorCamera);
}
void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept void SHCameraSystem::EditorCameraUpdate::Execute(double dt) noexcept
{ {
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem()); SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
@ -18,6 +69,7 @@ namespace SHADE
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A)) if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
{ {
//std::cout << "Camera movement: "<<right.x<<", " << right.y << std::endl;
camera.position -= right * dt * camera.movementSpeed; camera.position -= right * dt * camera.movementSpeed;
camera.dirtyView = true; camera.dirtyView = true;
} }
@ -58,6 +110,7 @@ namespace SHADE
camera.dirtyView = true; camera.dirtyView = true;
} }
//std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
system->UpdateCameraComponent(system->editorCamera); system->UpdateCameraComponent(system->editorCamera);
} }
@ -83,10 +136,26 @@ namespace SHADE
void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept void SHCameraSystem::UpdateCameraComponent(SHCameraComponent& camera) noexcept
{ {
if (SHComponentManager::HasComponent<SHTransformComponent>(camera.GetEID()) == true && &camera != &editorCamera)
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
SHVec3 rotation = transform->GetWorldRotation();
camera.pitch = SHMath::RadiansToDegrees(rotation.x);
camera.yaw = SHMath::RadiansToDegrees(rotation.y);
camera.roll = SHMath::RadiansToDegrees(rotation.z);
camera.position = transform->GetWorldPosition();
camera.dirtyView = true;
}
if (camera.dirtyView) if (camera.dirtyView)
{ {
SHVec3 view, right, UP; SHVec3 view, right, UP;
//ClampCameraRotation(camera);
GetCameraAxis(camera, view, right, UP); GetCameraAxis(camera, view, right, UP);
camera.viewMatrix = SHMatrix::Identity; camera.viewMatrix = SHMatrix::Identity;
@ -168,5 +237,55 @@ namespace SHADE
upVec = SHVec3::Cross(forward, right); upVec = SHVec3::Cross(forward, right);
} }
void SHCameraSystem::CameraSystemUpdate::Execute(double dt) noexcept
{
SHCameraSystem* system = static_cast<SHCameraSystem*>(GetSystem());
auto& dense = SHComponentManager::GetDense<SHCameraComponent>();
for (auto& cam : dense)
{
system->UpdateCameraComponent(cam);
}
for (auto& handle : system->directorHandleList)
{
handle->UpdateMatrix();
}
}
DirectorHandle SHCameraSystem::CreateDirector() noexcept
{
auto handle = directorLibrary.Create();
directorHandleList.emplace_back(handle);
return handle;
}
DirectorHandle SHCameraSystem::GetDirector(size_t index) noexcept
{
if (index < directorHandleList.size())
{
return directorHandleList[index];
}
else
{
return CreateDirector();
}
}
void SHCameraSystem::ClampCameraRotation(SHCameraComponent& camera) noexcept
{
if (camera.pitch > 85)
camera.SetPitch(85);
if (camera.pitch < -85)
camera.SetPitch(-85);
if (camera.roll > 85)
camera.SetRoll(85);
if (camera.roll < -85)
camera.SetRoll(-85);
}
} }

View File

@ -3,9 +3,10 @@
#include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHSystem.h"
#include "SHCameraComponent.h" #include "SHCameraComponent.h"
#include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/System/SHSystemRoutine.h"
#include "Resource/SHResourceLibrary.h"
#include "SHCameraDirector.h"
#include "SH_API.h" #include "SH_API.h"
namespace SHADE namespace SHADE
{ {
class SH_API SHCameraSystem final : public SHSystem class SH_API SHCameraSystem final : public SHSystem
@ -15,7 +16,8 @@ namespace SHADE
//This is not tied to any entity. Hence this EID should not be used. //This is not tied to any entity. Hence this EID should not be used.
SHCameraComponent editorCamera; SHCameraComponent editorCamera;
SHResourceLibrary<SHCameraDirector> directorLibrary;
std::vector<DirectorHandle> directorHandleList;
public: public:
SHCameraSystem(void) = default; SHCameraSystem(void) = default;
@ -34,13 +36,26 @@ namespace SHADE
}; };
friend class EditorCameraUpdate; friend class EditorCameraUpdate;
SHCameraComponent* GetEditorCamera (void) noexcept; class SH_API CameraSystemUpdate final: public SHSystemRoutine
{
public:
CameraSystemUpdate() : SHSystemRoutine("Camera System Update", false) {};
virtual void Execute(double dt)noexcept override final;
};
friend class CameraSystemUpdate;
SHCameraComponent* GetEditorCamera (void) noexcept;
void GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& up) const noexcept;
DirectorHandle CreateDirector() noexcept;
DirectorHandle GetDirector(size_t index) noexcept;
void ClampCameraRotation(SHCameraComponent& camera) noexcept;
void UpdateEditorCamera(double dt) noexcept;
protected: protected:
void UpdateCameraComponent(SHCameraComponent& camera) noexcept; void UpdateCameraComponent(SHCameraComponent& camera) noexcept;
void GetCameraAxis(SHCameraComponent const& camera, SHVec3& forward, SHVec3& right, SHVec3& up) const noexcept;
}; };

View File

@ -10,6 +10,7 @@
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Images/SHVkImage.h" #include "Graphics/Images/SHVkImage.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
@ -299,7 +300,7 @@ namespace SHADE
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. "); SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
return; return;
} }
boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout(); bindPointData[static_cast<uint32_t>(pipelineHdl->GetPipelineType())].boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline()); vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline());
} }
@ -358,9 +359,10 @@ namespace SHADE
} }
} }
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets) void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
{ {
vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); uint32_t bindPointIndex = static_cast<uint32_t>(bindPoint);
vkCommandBuffer.bindDescriptorSets(SHVkUtil::GetPipelineBindPointFromType(bindPoint), bindPointData[bindPointIndex].boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
} }
/***************************************************************************/ /***************************************************************************/
@ -452,6 +454,11 @@ namespace SHADE
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand)); vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
} }
void SHVkCommandBuffer::ComputeDispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept
{
vkCommandBuffer.dispatch (groupCountX, groupCountY, groupCountZ);
}
void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo) void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
{ {
vkCommandBuffer.copyBufferToImage vkCommandBuffer.copyBufferToImage
@ -500,9 +507,9 @@ namespace SHADE
// //vkCommandBuffer.pipelineBarrier() // //vkCommandBuffer.pipelineBarrier()
//} //}
void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout) noexcept void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept
{ {
boundPipelineLayoutHdl = pipelineLayout; bindPointData[static_cast<uint32_t>(pipelineType)].boundPipelineLayoutHdl = pipelineLayout;
} }
/***************************************************************************/ /***************************************************************************/
@ -513,12 +520,13 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept void SHVkCommandBuffer::SubmitPushConstants(SH_PIPELINE_TYPE bindPoint) const noexcept
{ {
vkCommandBuffer.pushConstants(boundPipelineLayoutHdl->GetVkPipelineLayout(), auto layoutHdl = bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl;
boundPipelineLayoutHdl->GetPushConstantInterface().GetShaderStageFlags(), vkCommandBuffer.pushConstants(layoutHdl->GetVkPipelineLayout(),
layoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
0, 0,
boundPipelineLayoutHdl->GetPushConstantInterface().GetSize(), pushConstantData); layoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
} }
/***************************************************************************/ /***************************************************************************/
@ -695,7 +703,7 @@ namespace SHADE
, usageFlags{ rhs.usageFlags } , usageFlags{ rhs.usageFlags }
, commandBufferCount{ rhs.commandBufferCount } , commandBufferCount{ rhs.commandBufferCount }
, parentPool{ rhs.parentPool } , parentPool{ rhs.parentPool }
, boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl } , bindPointData{ std::move (rhs.bindPointData)}
{ {
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
@ -728,7 +736,7 @@ namespace SHADE
usageFlags = rhs.usageFlags; usageFlags = rhs.usageFlags;
commandBufferCount = rhs.commandBufferCount; commandBufferCount = rhs.commandBufferCount;
parentPool = rhs.parentPool; parentPool = rhs.parentPool;
boundPipelineLayoutHdl = rhs.boundPipelineLayoutHdl; bindPointData = std::move(rhs.bindPointData);
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
rhs.vkCommandBuffer = VK_NULL_HANDLE; rhs.vkCommandBuffer = VK_NULL_HANDLE;

View File

@ -6,6 +6,7 @@
#include "SHCommandPoolResetMode.h" #include "SHCommandPoolResetMode.h"
#include "Resource/SHResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h" #include "Graphics/Pipeline/SHVkPipelineLayout.h"
#include "Graphics/Pipeline/SHPipelineType.h"
namespace SHADE namespace SHADE
{ {
@ -39,7 +40,14 @@ namespace SHADE
friend class SHResourceLibrary<SHVkCommandBuffer>; friend class SHResourceLibrary<SHVkCommandBuffer>;
static constexpr uint16_t PUSH_CONSTANT_SIZE = 512; static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;
private: private:
struct PipelineBindPointData
{
//! The currently bound pipeline
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
};
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -66,8 +74,8 @@ namespace SHADE
//! The command pool that this command buffer belongs to //! The command pool that this command buffer belongs to
Handle<SHVkCommandPool> parentPool; Handle<SHVkCommandPool> parentPool;
//! The currently bound pipeline //! Every command buffer will have a set of pipeline bind point specific data
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl; std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData;
//! The push constant data for the command buffer //! The push constant data for the command buffer
uint8_t pushConstantData[PUSH_CONSTANT_SIZE]; uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
@ -112,13 +120,16 @@ namespace SHADE
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept; void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept;
void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept; void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept;
void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept; void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept;
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets); void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
// Draw Commands // Draw Commands
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept; void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept; void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount); void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
// Compute Commands
void ComputeDispatch (uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept;
// Buffer Copy // Buffer Copy
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo); void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo); void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
@ -138,13 +149,13 @@ namespace SHADE
// Push Constant variable setting // Push Constant variable setting
template <typename T> template <typename T>
void SetPushConstantVariable(std::string variableName, T const& data) noexcept void SetPushConstantVariable(std::string variableName, T const& data, SH_PIPELINE_TYPE bindPoint) noexcept
{ {
memcpy (static_cast<uint8_t*>(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T)); memcpy (static_cast<uint8_t*>(pushConstantData) + bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
}; };
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout) noexcept; void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept;
void SubmitPushConstants (void) const noexcept; void SubmitPushConstants (SH_PIPELINE_TYPE bindPoint) const noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */

View File

@ -25,7 +25,8 @@ namespace SHADE
} }
SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept
: device{ rhs.device } : ISelfHandle (rhs)
, device{ rhs.device }
, pool{ rhs.pool } , pool{ rhs.pool }
{ {
rhs.pool = VK_NULL_HANDLE; rhs.pool = VK_NULL_HANDLE;

View File

@ -91,7 +91,7 @@ namespace SHADE
// new write for the binding // new write for the binding
updater.writeInfos.emplace_back(); updater.writeInfos.emplace_back();
updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1); updater.writeHashMap.try_emplace(writeHash, static_cast<uint32_t>(updater.writeInfos.size()) - 1u);
auto& writeInfo = updater.writeInfos.back(); auto& writeInfo = updater.writeInfos.back();
// Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in // Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in
@ -102,10 +102,10 @@ namespace SHADE
//case vk::DescriptorType::eSampler: //case vk::DescriptorType::eSampler:
//case vk::DescriptorType::eSampledImage: //case vk::DescriptorType::eSampledImage:
case vk::DescriptorType::eCombinedImageSampler: case vk::DescriptorType::eCombinedImageSampler:
case vk::DescriptorType::eStorageImage:
case vk::DescriptorType::eInputAttachment:
writeInfo.descImageInfos.resize(descriptorCount); writeInfo.descImageInfos.resize(descriptorCount);
break; break;
//case vk::DescriptorType::eStorageImage:
// break;
case vk::DescriptorType::eUniformTexelBuffer: case vk::DescriptorType::eUniformTexelBuffer:
case vk::DescriptorType::eStorageTexelBuffer: case vk::DescriptorType::eStorageTexelBuffer:
case vk::DescriptorType::eUniformBuffer: case vk::DescriptorType::eUniformBuffer:
@ -165,6 +165,7 @@ namespace SHADE
if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size()) if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size())
{ {
SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. "); SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. ");
return;
} }
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i) for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)

View File

@ -31,6 +31,8 @@ namespace SHADE
class SHVkDescriptorSetGroup class SHVkDescriptorSetGroup
{ {
public: public:
using viewSamplerLayout = std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */ /* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -233,6 +233,8 @@ namespace SHADE
, vmaAllocator{rhs.vmaAllocator} , vmaAllocator{rhs.vmaAllocator}
, nonDedicatedBestIndex {0} , nonDedicatedBestIndex {0}
, parentPhysicalDeviceHdl {rhs.parentPhysicalDeviceHdl} , parentPhysicalDeviceHdl {rhs.parentPhysicalDeviceHdl}
, uboBufferMemoryAlignment{ 0 }
, ssboBufferMemoryAlignment{ 0 }
{ {
rhs.vkLogicalDevice = VK_NULL_HANDLE; rhs.vkLogicalDevice = VK_NULL_HANDLE;
} }
@ -261,6 +263,8 @@ namespace SHADE
vmaAllocator = rhs.vmaAllocator; vmaAllocator = rhs.vmaAllocator;
nonDedicatedBestIndex = 0; nonDedicatedBestIndex = 0;
parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl; parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
uboBufferMemoryAlignment = rhs.uboBufferMemoryAlignment;
ssboBufferMemoryAlignment = rhs.ssboBufferMemoryAlignment;
rhs.vkLogicalDevice = VK_NULL_HANDLE; rhs.vkLogicalDevice = VK_NULL_HANDLE;
@ -529,6 +533,11 @@ namespace SHADE
} }
Handle<SHVkPipeline> SHVkLogicalDevice::CreateComputePipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl) noexcept
{
return SHVkInstance::GetResourceManager().Create <SHVkPipeline>(GetHandle(), pipelineLayoutHdl);
}
Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept
{ {
return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params); return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params);

View File

@ -181,6 +181,11 @@ namespace SHADE
Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkRenderpass> const& renderpassHdl,
Handle<SHSubpass> subpass Handle<SHSubpass> subpass
) noexcept; ) noexcept;
Handle<SHVkPipeline> CreateComputePipeline (
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl
) noexcept;
Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept; Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept; Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;

View File

@ -385,7 +385,7 @@ namespace SHADE
cmdBuffer->BindDescriptorSet cmdBuffer->BindDescriptorSet
( (
matPropsDescSet[frameIndex], matPropsDescSet[frameIndex],
vk::PipelineBindPoint::eGraphics, SH_PIPELINE_TYPE::GRAPHICS,
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
dynamicOffset dynamicOffset
); );

View File

@ -25,7 +25,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp) SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
: subpass { sp } : subpass{ sp }
{} {}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -63,6 +63,14 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t PER_INSTANCE = 3; static constexpr uint32_t PER_INSTANCE = 3;
/***************************************************************************/
/*!
\brief
DescriptorSet Index for render graph resources.
*/
/***************************************************************************/
static constexpr uint32_t RENDERGRAPH_RESOURCE = 4;
}; };

View File

@ -115,6 +115,23 @@ namespace SHADE
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true); graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
shaderSourceLibrary.Init("../../TempShaderFolder/");
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
cubeVS->Reflect();
cubeFS->Reflect();
greyscale->Reflect();
} }
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -130,6 +147,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto windowDims = window->GetWindowSize(); auto windowDims = window->GetWindowSize();
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
// Set Up Cameras // Set Up Cameras
screenCamera = resourceManager.Create<SHCamera>(); screenCamera = resourceManager.Create<SHCamera>();
@ -154,21 +172,21 @@ namespace SHADE
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain); worldRenderGraph->Init(device, swapchain);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, 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("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);
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
//First subpass to write to G-Buffer //First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
gBufferWriteSubpass->AddColorOutput("Scene"); gBufferWriteSubpass->AddColorOutput("Scene Pre-Process");
gBufferWriteSubpass->AddColorOutput("Entity ID"); gBufferWriteSubpass->AddColorOutput("Entity ID");
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
// We do this to just transition our scene layout to shader read auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition"); node->AddNodeCompute (greyscale, {"Scene Pre-Process", "Scene"});
sceneLayoutTransitionSubpass->AddInput("Scene");
// Generate world render graph // Generate world render graph
worldRenderGraph->Generate(); worldRenderGraph->Generate();
@ -177,20 +195,13 @@ namespace SHADE
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph); worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera); worldRenderer->SetCamera(worldCamera);
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
shaderSourceLibrary.Init("../../TempShaderFolder/");
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
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");
cubeVS->Reflect();
cubeFS->Reflect();
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass); defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
} }
void SHGraphicsSystem::InitMiddleEnd(void) noexcept void SHGraphicsSystem::InitMiddleEnd(void) noexcept
@ -323,21 +334,7 @@ namespace SHADE
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>(); auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
#ifdef SHEDITOR
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
{
worldRenderer->SetViewProjectionMatrix(SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
}
else
{
// main camera
}
#else
// main camera
#endif
// For every viewport // For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex) for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
@ -360,7 +357,7 @@ namespace SHADE
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);
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout()); currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
// Bind all the buffers required for meshes // Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA) for (auto& [buffer, bindingPoint] : MESH_DATA)
@ -380,14 +377,29 @@ namespace SHADE
currentCmdBuffer->BindDescriptorSet currentCmdBuffer->BindDescriptorSet
( (
textureDescSet, textureDescSet,
vk::PipelineBindPoint::eGraphics, SH_PIPELINE_TYPE::GRAPHICS,
0, 0,
texDynamicOffset texDynamicOffset
); );
} }
// bind camera data // bind camera data
//renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#ifdef SHEDITOR
if (renderers[renIndex] == worldRenderer)
{
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
}
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#endif
// Draw first // Draw first
renderers[renIndex]->Draw(frameIndex, descPool); renderers[renIndex]->Draw(frameIndex, descPool);
@ -726,8 +738,8 @@ namespace SHADE
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>(); auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
#ifdef SHEDITOR #ifdef SHEDITOR
cameraSystem->GetEditorCamera()->SetWidth(resizeWidth); cameraSystem->GetEditorCamera()->SetWidth(static_cast<float>(resizeWidth));
cameraSystem->GetEditorCamera()->SetHeight(resizeHeight); cameraSystem->GetEditorCamera()->SetHeight(static_cast<float>(resizeHeight));
#else #else
#endif #endif

View File

@ -68,7 +68,7 @@ namespace SHADE
{ {
std::vector combinedImageSampler std::vector combinedImageSampler
{ {
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal), std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eGeneral),
}; };
// 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

View File

@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Camera/SHCameraDirector.h"
namespace SHADE namespace SHADE
{ {
@ -65,6 +66,11 @@ namespace SHADE
camera = _camera; camera = _camera;
} }
void SHRenderer::SetCameraDirector(Handle<SHCameraDirector> director) noexcept
{
cameraDirector = director;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Drawing Functions */ /* Drawing Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -75,15 +81,22 @@ namespace SHADE
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{ {
if (camera) if (camera && cameraDirector)
{ {
UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
}
}
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept
{
SetViewProjectionMatrix(exteriorMatrix);
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix(); //cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex); cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize }; std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 }); cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
}
} }
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept void SHRenderer::UpdateCameraDataToBuffer(void) noexcept

View File

@ -40,6 +40,7 @@ namespace SHADE
class SHGraphicsGlobalData; class SHGraphicsGlobalData;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkBuffer; class SHVkBuffer;
class SHCameraDirector;
struct SHShaderCameraData struct SHShaderCameraData
{ {
@ -71,12 +72,14 @@ namespace SHADE
/* Camera Registration */ /* Camera Registration */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void SetCamera(Handle<SHCamera> _camera); void SetCamera(Handle<SHCamera> _camera);
void SetCameraDirector (Handle<SHCameraDirector> director) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Drawing Functions */ /* Drawing Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept; void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
void UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept;
void UpdateCameraDataToBuffer (void) noexcept; void UpdateCameraDataToBuffer (void) noexcept;
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept; void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept;
@ -99,6 +102,8 @@ namespace SHADE
Handle<SHVkDescriptorSetGroup> cameraDescriptorSet; Handle<SHVkDescriptorSetGroup> cameraDescriptorSet;
Handle<SHVkBuffer> cameraBuffer; Handle<SHVkBuffer> cameraBuffer;
Handle<SHCameraDirector> cameraDirector;
// we really only need 1 copy even though we need %swapchainImages copies for // we really only need 1 copy even though we need %swapchainImages copies for
// GPU. // GPU.
SHShaderCameraData cpuCameraData; SHShaderCameraData cpuCameraData;

View File

@ -8,7 +8,7 @@
namespace SHADE namespace SHADE
{ {
Handle<SHVkPipeline> SHPipelineLibrary::CreateDrawPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
{ {
SHPipelineLayoutParams params SHPipelineLayoutParams params
{ {
@ -52,7 +52,7 @@ namespace SHADE
newPipeline->ConstructPipeline(); newPipeline->ConstructPipeline();
// Emplace the new pipeline // Emplace the new pipeline
pipelines.emplace (vsFsPair, newPipeline); graphicsPipelines.emplace (vsFsPair, newPipeline);
return newPipeline; return newPipeline;
} }
@ -62,19 +62,19 @@ namespace SHADE
logicalDevice = device; logicalDevice = device;
} }
Handle<SHVkPipeline> SHPipelineLibrary::GetDrawPipline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept Handle<SHVkPipeline> SHPipelineLibrary::GetGraphicsPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
{ {
// return the pipeline requested for // return the pipeline requested for
if (pipelines.contains(vsFsPair)) if (graphicsPipelines.contains(vsFsPair))
return pipelines.at(vsFsPair); return graphicsPipelines.at(vsFsPair);
else else
return {}; return {};
} }
bool SHPipelineLibrary::CheckDrawPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept bool SHPipelineLibrary::CheckGraphicsPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
{ {
// Returns if a pipeline exists or not // Returns if a pipeline exists or not
return pipelines.contains(vsFsPair); return graphicsPipelines.contains(vsFsPair);
} }
} }

View File

@ -23,19 +23,19 @@ namespace SHADE
Handle<SHVkLogicalDevice> logicalDevice; Handle<SHVkLogicalDevice> logicalDevice;
//! a map of pipelines that are hashed using a pair of shader module handles //! a map of pipelines that are hashed using a pair of shader module handles
std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> pipelines; std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> graphicsPipelines;
public: public:
void Init (Handle<SHVkLogicalDevice> device) noexcept; void Init (Handle<SHVkLogicalDevice> device) noexcept;
// Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader // Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader
Handle<SHVkPipeline> CreateDrawPipeline ( Handle<SHVkPipeline> CreateGraphicsPipelines (
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
Handle<SHVkRenderpass> renderpass, Handle<SHVkRenderpass> renderpass,
Handle<SHSubpass> subpass Handle<SHSubpass> subpass
) noexcept; ) noexcept;
Handle<SHVkPipeline> GetDrawPipline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept; Handle<SHVkPipeline> GetGraphicsPipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
bool CheckDrawPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept; bool CheckGraphicsPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
}; };
} }

View File

@ -5,9 +5,13 @@ namespace SHADE
{ {
enum class SH_PIPELINE_TYPE enum class SH_PIPELINE_TYPE
{ {
GRAPHICS, GRAPHICS = 0,
COMPUTE, COMPUTE,
RAY_TRACING,
NUM_TYPES,
}; };
} }
#endif #endif

View File

@ -4,6 +4,7 @@
#include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Debugging/SHVulkanDebugUtil.h" #include "Graphics/Debugging/SHVulkanDebugUtil.h"
#include "Graphics/RenderGraph/SHRenderGraph.h" #include "Graphics/RenderGraph/SHRenderGraph.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -171,6 +172,29 @@ namespace SHADE
void SHVkPipeline::CreateComputePipeline(void) noexcept void SHVkPipeline::CreateComputePipeline(void) noexcept
{ {
auto shaderModule = pipelineLayout->GetShaderModules()[0];
vk::PipelineShaderStageCreateInfo shaderStageCreateInfo
{
.stage = vk::ShaderStageFlagBits::eCompute,
.module = shaderModule->GetVkShaderModule(),
.pName = shaderModule->GetEntryPoint().c_str(),
};
vk::ComputePipelineCreateInfo cpCreateInfo
{
.flags = {},
.stage = shaderStageCreateInfo,
.layout = pipelineLayout->GetVkPipelineLayout(),
};
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createComputePipelines({}, 1, &cpCreateInfo, nullptr, &vkPipeline); result != vk::Result::eSuccess)
SHVulkanDebugUtil::ReportVkError(result, "Failed to create Compute Pipeline. ");
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created a Compute Pipeline. ");
created = true;
}
} }
@ -245,7 +269,7 @@ namespace SHADE
, logicalDeviceHdl{ rhs.logicalDeviceHdl } , logicalDeviceHdl{ rhs.logicalDeviceHdl }
, pipelineLayout { rhs.pipelineLayout } , pipelineLayout { rhs.pipelineLayout }
{ {
vkPipeline = VK_NULL_HANDLE; rhs.vkPipeline = VK_NULL_HANDLE;
} }
/***************************************************************************/ /***************************************************************************/
@ -285,6 +309,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
SHVkPipeline::~SHVkPipeline(void) noexcept SHVkPipeline::~SHVkPipeline(void) noexcept
{ {
if (vkPipeline)
logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr); logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr);
} }
@ -313,7 +338,7 @@ namespace SHADE
created = rhs.created; created = rhs.created;
logicalDeviceHdl = rhs.logicalDeviceHdl; logicalDeviceHdl = rhs.logicalDeviceHdl;
vkPipeline = VK_NULL_HANDLE; rhs.vkPipeline = VK_NULL_HANDLE;
return *this; return *this;
} }
@ -399,18 +424,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept
{ {
switch (pipelineType) return SHVkUtil::GetPipelineBindPointFromType(pipelineType);
{
case SH_PIPELINE_TYPE::GRAPHICS:
return vk::PipelineBindPoint::eGraphics;
case SH_PIPELINE_TYPE::COMPUTE:
return vk::PipelineBindPoint::eCompute;
break;
default:
return vk::PipelineBindPoint::eGraphics;
break;
}
} }
/***************************************************************************/ /***************************************************************************/
@ -450,4 +464,9 @@ namespace SHADE
return pipelineLayout; return pipelineLayout;
} }
SH_PIPELINE_TYPE SHVkPipeline::GetPipelineType(void) const noexcept
{
return pipelineType;
}
} }

View File

@ -77,6 +77,7 @@ namespace SHADE
vk::Pipeline GetVkPipeline (void) const noexcept; vk::Pipeline GetVkPipeline (void) const noexcept;
bool GetIsCreated (void) const noexcept; bool GetIsCreated (void) const noexcept;
Handle<SHVkPipelineLayout> GetPipelineLayout (void) const noexcept; Handle<SHVkPipelineLayout> GetPipelineLayout (void) const noexcept;
SH_PIPELINE_TYPE GetPipelineType (void) const noexcept;
}; };
} }

View File

@ -216,9 +216,18 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept
{ {
// pipeline layouts contain global layouts first, then layouts for allocation
descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size()); descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
// Settle allocate layouts first // First we insert the global layouts
for (auto const& layout : descriptorSetLayoutsGlobal)
{
descriptorSetLayoutsPipeline.emplace_back(layout);
//vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
}
// Then the allocate layouts
vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size()); vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size());
for (auto const& layout : descriptorSetLayoutsAllocate) for (auto const& layout : descriptorSetLayoutsAllocate)
{ {
@ -226,18 +235,13 @@ namespace SHADE
vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle()); vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle());
} }
// pipeline layouts contain global layouts first, then layouts for allocation for (auto const& layout : descriptorSetLayoutsPipeline)
vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
// First we insert the global layouts
for (auto const& layout : descriptorSetLayoutsGlobal)
{ {
descriptorSetLayoutsPipeline.emplace_back(layout);
vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle()); vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
} }
// Then we append layouts for allocation at the back of the vector // Then we append layouts for allocation at the back of the vector
std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline)); //std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
} }
/***************************************************************************/ /***************************************************************************/
@ -294,6 +298,7 @@ namespace SHADE
, descriptorSetLayoutsGlobal{pipelineLayoutParams.globalDescSetLayouts } // do a copy, some other pipeline layout might need this , descriptorSetLayoutsGlobal{pipelineLayoutParams.globalDescSetLayouts } // do a copy, some other pipeline layout might need this
, descriptorSetLayoutsAllocate{} , descriptorSetLayoutsAllocate{}
, vkDescriptorSetLayoutsAllocate{} , vkDescriptorSetLayoutsAllocate{}
, descriptorSetLayoutsPipeline{}
, vkDescriptorSetLayoutsPipeline{} , vkDescriptorSetLayoutsPipeline{}
{ {
for (auto& mod : shaderModules) for (auto& mod : shaderModules)
@ -318,6 +323,7 @@ namespace SHADE
, descriptorSetLayoutsGlobal{} , descriptorSetLayoutsGlobal{}
, descriptorSetLayoutsAllocate{} , descriptorSetLayoutsAllocate{}
, vkDescriptorSetLayoutsAllocate{} , vkDescriptorSetLayoutsAllocate{}
, descriptorSetLayoutsPipeline{}
, vkDescriptorSetLayoutsPipeline{} , vkDescriptorSetLayoutsPipeline{}
{ {
@ -368,7 +374,8 @@ namespace SHADE
, descriptorSetLayoutsGlobal {std::move (rhs.descriptorSetLayoutsGlobal)} , descriptorSetLayoutsGlobal {std::move (rhs.descriptorSetLayoutsGlobal)}
, descriptorSetLayoutsAllocate {std::move (rhs.descriptorSetLayoutsAllocate)} , descriptorSetLayoutsAllocate {std::move (rhs.descriptorSetLayoutsAllocate)}
, vkDescriptorSetLayoutsAllocate{std::move (rhs.vkDescriptorSetLayoutsAllocate)} , vkDescriptorSetLayoutsAllocate{std::move (rhs.vkDescriptorSetLayoutsAllocate)}
, vkDescriptorSetLayoutsPipeline{std::move (rhs.vkDescriptorSetLayoutsAllocate)} , descriptorSetLayoutsPipeline { std::move(rhs.descriptorSetLayoutsPipeline) }
, vkDescriptorSetLayoutsPipeline{ std::move(rhs.vkDescriptorSetLayoutsPipeline) }
{ {
rhs.vkPipelineLayout = VK_NULL_HANDLE; rhs.vkPipelineLayout = VK_NULL_HANDLE;
} }
@ -441,12 +448,12 @@ namespace SHADE
return {}; return {};
} }
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
{ {
return descriptorSetLayoutsPipeline; return descriptorSetLayoutsPipeline;
} }
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
{ {
return descriptorSetLayoutsAllocate; return descriptorSetLayoutsAllocate;
} }
@ -464,7 +471,8 @@ namespace SHADE
descriptorSetLayoutsGlobal = std::move(rhs.descriptorSetLayoutsGlobal); descriptorSetLayoutsGlobal = std::move(rhs.descriptorSetLayoutsGlobal);
descriptorSetLayoutsAllocate = std::move(rhs.descriptorSetLayoutsAllocate); descriptorSetLayoutsAllocate = std::move(rhs.descriptorSetLayoutsAllocate);
vkDescriptorSetLayoutsAllocate = std::move(rhs.vkDescriptorSetLayoutsAllocate); vkDescriptorSetLayoutsAllocate = std::move(rhs.vkDescriptorSetLayoutsAllocate);
vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsAllocate); descriptorSetLayoutsPipeline = std::move(rhs.descriptorSetLayoutsPipeline);
vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsPipeline);
rhs.vkPipelineLayout = VK_NULL_HANDLE; rhs.vkPipelineLayout = VK_NULL_HANDLE;

View File

@ -78,8 +78,8 @@ namespace SHADE
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept; vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept; SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept;
Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept; Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsPipeline(void) const noexcept; std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsPipeline(void) const noexcept;
std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsAllocate(void) const noexcept; std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsAllocate(void) const noexcept;
}; };
} }

View File

@ -10,6 +10,8 @@ namespace SHADE
DEPTH = 0x04, DEPTH = 0x04,
STENCIL = 0x08, STENCIL = 0x08,
DEPTH_STENCIL = 0x10, DEPTH_STENCIL = 0x10,
INPUT = 0x20 INPUT = 0x20,
STORAGE = 0x40
}; };
} }

View File

@ -9,6 +9,8 @@
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "SHAttachmentDescInitParams.h" #include "SHAttachmentDescInitParams.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
namespace SHADE namespace SHADE
{ {
@ -52,12 +54,12 @@ namespace SHADE
// If we set to // If we set to
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1)) if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
{ {
w = swapchainHdl->GetSwapchainImage(0)->GetWidth(); w = renderGraphStorage->swapchain->GetSwapchainImage(0)->GetWidth();
h = swapchainHdl->GetSwapchainImage(0)->GetHeight(); h = renderGraphStorage->swapchain->GetSwapchainImage(0)->GetHeight();
format = swapchainHdl->GetSurfaceFormatKHR().format; format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
} }
graphResources.try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(logicalDeviceHdl, swapchainHdl, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags)); renderGraphStorage->graphResources->try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
} }
/***************************************************************************/ /***************************************************************************/
@ -77,36 +79,38 @@ namespace SHADE
for (uint32_t i = 0; auto& node : nodes) for (uint32_t i = 0; auto& node : nodes)
{ {
// key is handle ID, value is pair (first is initial layout, second is final layout). // key is handle ID, value is final layout.
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts; std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
if (node->subpasses.empty()) if (node->subpasses.empty())
{ {
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. "); SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
return; return;
} }
// attempt to get all final layouts for all resources
for (auto& subpass : node->subpasses) for (auto& subpass : node->subpasses)
{ {
for (auto& color : subpass->colorReferences) for (auto& color : subpass->colorReferences)
{ {
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))) if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)))
resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR; resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
else else
resourceAttLayouts[color.attachment] = color.layout; resourceAttFinalLayouts[color.attachment] = color.layout;
} }
for (auto& depth : subpass->depthReferences) for (auto& depth : subpass->depthReferences)
resourceAttLayouts[depth.attachment] = depth.layout; resourceAttFinalLayouts[depth.attachment] = depth.layout;
for (auto& input : subpass->inputReferences) for (auto& input : subpass->inputReferences)
resourceAttLayouts[input.attachment] = input.layout; resourceAttFinalLayouts[input.attachment] = input.layout;
} }
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j) for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
{ {
auto& att = node->attachmentDescriptions[j]; auto& att = node->attachmentDescriptions[j];
att.initialLayout = vk::ImageLayout::eUndefined; att.initialLayout = vk::ImageLayout::eUndefined;
att.finalLayout = resourceAttLayouts[j]; att.finalLayout = resourceAttFinalLayouts[j];
} }
++i; ++i;
} }
@ -292,6 +296,9 @@ namespace SHADE
dep.dstAccessMask = dstAccess; dep.dstAccessMask = dstAccess;
dep.srcStageMask = srcStage; dep.srcStageMask = srcStage;
// initialize input descriptors
node->subpasses[i]->CreateInputDescriptors();
} }
} }
} }
@ -343,10 +350,18 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
{ {
logicalDeviceHdl = logicalDevice; resourceManager = std::make_shared<SHResourceHub>();
swapchainHdl = swapchain;
renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>();
renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
renderGraphStorage->logicalDevice = logicalDevice;
renderGraphStorage->swapchain = swapchain;
renderGraphStorage->resourceManager = resourceManager;
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
} }
/***************************************************************************/ /***************************************************************************/
@ -361,21 +376,16 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraph::SHRenderGraph(void) noexcept SHRenderGraph::SHRenderGraph(void) noexcept
: logicalDeviceHdl{ } : renderGraphStorage{}
, swapchainHdl{ }
, nodes{} , nodes{}
, graphResources{}
, resourceManager{nullptr} , resourceManager{nullptr}
{ {
resourceManager = std::make_shared<SHResourceHub>();
} }
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
: logicalDeviceHdl{ rhs.logicalDeviceHdl } : renderGraphStorage{ rhs.renderGraphStorage }
, swapchainHdl{ rhs.swapchainHdl }
, nodeIndexing{ std::move(rhs.nodeIndexing) } , nodeIndexing{ std::move(rhs.nodeIndexing) }
, nodes{ std::move(rhs.nodes) } , nodes{ std::move(rhs.nodes) }
, graphResources{ std::move(rhs.graphResources) }
, resourceManager{ std::move(rhs.resourceManager) } , resourceManager{ std::move(rhs.resourceManager) }
{ {
@ -386,11 +396,9 @@ namespace SHADE
if (&rhs == this) if (&rhs == this)
return *this; return *this;
logicalDeviceHdl = rhs.logicalDeviceHdl; renderGraphStorage = rhs.renderGraphStorage;
swapchainHdl = rhs.swapchainHdl;
nodeIndexing = std::move(rhs.nodeIndexing); nodeIndexing = std::move(rhs.nodeIndexing);
nodes = std::move(rhs.nodes); nodes = std::move(rhs.nodes);
graphResources = std::move(rhs.graphResources);
resourceManager = std::move(rhs.resourceManager); resourceManager = std::move(rhs.resourceManager);
return *this; return *this;
@ -426,12 +434,12 @@ namespace SHADE
for (auto const& instruction : resourceInstruction) for (auto const& instruction : resourceInstruction)
{ {
// If the resource that the new node is requesting for exists, allow the graph to reference it // If the resource that the new node is requesting for exists, allow the graph to reference it
if (graphResources.contains(instruction.resourceName)) if (renderGraphStorage->graphResources->contains(instruction.resourceName))
{ {
descInitParams.push_back( descInitParams.push_back(
{ {
.resourceHdl = graphResources.at(instruction.resourceName), .resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName),
.dontClearOnLoad = false, .dontClearOnLoad = instruction.dontClearOnLoad,
} }
); );
} }
@ -456,7 +464,7 @@ namespace SHADE
} }
} }
nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(descInitParams), std::move(predecessors), &graphResources)); nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(renderGraphStorage, std::move(descInitParams), std::move(predecessors)));
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u); nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
return nodes.at(nodeIndexing[nodeName]); return nodes.at(nodeIndexing[nodeName]);
} }
@ -476,12 +484,31 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Generate(void) noexcept void SHRenderGraph::Generate(void) noexcept
{ {
CheckForNodeComputes();
ConfigureAttachmentDescriptions(); ConfigureAttachmentDescriptions();
ConfigureSubpasses(); ConfigureSubpasses();
ConfigureRenderpasses(); ConfigureRenderpasses();
ConfigureFramebuffers(); ConfigureFramebuffers();
} }
/***************************************************************************/
/*!
\brief
This function goes through all renderpasses and checks for existence of
node computes. If they exist, adds dummy subpasses to transition resources
into general.
*/
/***************************************************************************/
void SHRenderGraph::CheckForNodeComputes(void) noexcept
{
for (auto& node : nodes)
{
node->AddDummySubpassIfNeeded();
}
}
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a // TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
// better way to manage these // better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
@ -501,7 +528,7 @@ namespace SHADE
void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
{ {
// resize resources // resize resources
for (auto& [name, resource]: graphResources) for (auto& [name, resource] : *renderGraphStorage->graphResources)
resource->HandleResize(newWidth, newHeight); resource->HandleResize(newWidth, newHeight);
for (auto& node : nodes) for (auto& node : nodes)
@ -521,9 +548,9 @@ namespace SHADE
Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept
{ {
if (graphResources.contains(resourceName)) if (renderGraphStorage->graphResources->contains(resourceName))
{ {
return graphResources.at(resourceName); return renderGraphStorage->graphResources->at(resourceName);
} }
return {}; return {};
} }

View File

@ -30,7 +30,8 @@ namespace SHADE
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHRenderGraphNode; class SHRenderGraphNode;
class SHGraphicsGlobalData; class SHGraphicsGlobalData;
class SHVkDescriptorPool;
class SHRenderGraphStorage;
class SH_API SHRenderGraph class SH_API SHRenderGraph
{ {
@ -56,10 +57,8 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! swapchain used for querying image count Handle<SHRenderGraphStorage> renderGraphStorage;
Handle<SHVkSwapchain> swapchainHdl;
//! For indexing render graph node container //! For indexing render graph node container
std::map<std::string, uint32_t> nodeIndexing; std::map<std::string, uint32_t> nodeIndexing;
@ -67,9 +66,6 @@ namespace SHADE
//! Render graph nodes //! Render graph nodes
std::vector<Handle<SHRenderGraphNode>> nodes; std::vector<Handle<SHRenderGraphNode>> nodes;
//! Resources that exist for the entire render graph
std::unordered_map<std::string, Handle<SHRenderGraphResource>> graphResources;
//! Resource library for graph handles //! Resource library for graph handles
std::shared_ptr<SHResourceHub> resourceManager; std::shared_ptr<SHResourceHub> resourceManager;
@ -85,13 +81,14 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept; void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept;
void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept; Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
void Generate (void) noexcept; void Generate (void) noexcept;
void CheckForNodeComputes (void) noexcept;
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept; void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void FinaliseBatch (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept; void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -6,6 +6,9 @@
#include "Graphics/Framebuffer/SHVkFramebuffer.h" #include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "SHSubpass.h" #include "SHSubpass.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -21,7 +24,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHRenderGraphNode::CreateRenderpass(void) noexcept void SHRenderGraphNode::CreateRenderpass(void) noexcept
{ {
renderpass = logicalDeviceHdl->CreateRenderpass(attachmentDescriptions, spDescs, spDeps); renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
} }
/***************************************************************************/ /***************************************************************************/
@ -53,7 +56,7 @@ namespace SHADE
} }
framebuffers[i] = logicalDeviceHdl->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight); framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
} }
} }
@ -79,9 +82,18 @@ namespace SHADE
fbHeight = attResources[j]->height; fbHeight = attResources[j]->height;
} }
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight); framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
} }
for (auto& subpass : subpasses)
{
subpass->HandleResize();
}
for (auto& nodeCompute : nodeComputes)
{
nodeCompute->HandleResize();
}
} }
/***************************************************************************/ /***************************************************************************/
@ -104,8 +116,8 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphNode::SHRenderGraphNode(std::shared_ptr<SHResourceHub> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept SHRenderGraphNode::SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept
: logicalDeviceHdl{ logicalDevice } : graphStorage{ renderGraphStorage}
, renderpass{} , renderpass{}
, framebuffers{} , framebuffers{}
, prereqNodes{ std::move(predecessors) } , prereqNodes{ std::move(predecessors) }
@ -115,11 +127,10 @@ namespace SHADE
, subpasses{} , subpasses{}
, executed{ false } , executed{ false }
, configured{ false } , configured{ false }
, resourceManager{ rm } , nodeComputes{}
, ptrToResources{ resources }
{ {
// pipeline library initialization // pipeline library initialization
pipelineLibrary.Init(logicalDeviceHdl); pipelineLibrary.Init(graphStorage->logicalDevice);
// Store all the handles to resources // Store all the handles to resources
attResources.reserve (attDescInitParams.size()); attResources.reserve (attDescInitParams.size());
@ -155,15 +166,14 @@ namespace SHADE
if (!containsSwapchainImage) if (!containsSwapchainImage)
framebuffers.resize(1); framebuffers.resize(1);
else else
framebuffers.resize(swapchain->GetNumImages()); framebuffers.resize(graphStorage->swapchain->GetNumImages());
// At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be // At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be
// deferred to when renderpasses are also created. // deferred to when renderpasses are also created.
} }
SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
: resourceManager{ std::move (rhs.resourceManager) } : graphStorage{ rhs.graphStorage}
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
, renderpass{ rhs.renderpass } , renderpass{ rhs.renderpass }
, framebuffers{ std::move(rhs.framebuffers) } , framebuffers{ std::move(rhs.framebuffers) }
, prereqNodes{ std::move(rhs.prereqNodes) } , prereqNodes{ std::move(rhs.prereqNodes) }
@ -174,11 +184,11 @@ namespace SHADE
, subpassIndexing{ std::move(rhs.subpassIndexing) } , subpassIndexing{ std::move(rhs.subpassIndexing) }
, configured{ rhs.configured } , configured{ rhs.configured }
, executed{ rhs.executed } , executed{ rhs.executed }
, ptrToResources{ rhs.ptrToResources }
, pipelineLibrary{ std::move(rhs.pipelineLibrary) } , pipelineLibrary{ std::move(rhs.pipelineLibrary) }
, batcher{ std::move(rhs.batcher) } , batcher{ std::move(rhs.batcher) }
, spDescs{ std::move(rhs.spDescs) } , spDescs{ std::move(rhs.spDescs) }
, spDeps{ std::move(rhs.spDeps) } , spDeps{ std::move(rhs.spDeps) }
, nodeComputes{ std::move(rhs.nodeComputes) }
{ {
rhs.renderpass = {}; rhs.renderpass = {};
@ -189,8 +199,7 @@ namespace SHADE
if (&rhs == this) if (&rhs == this)
return *this; return *this;
resourceManager = std::move(rhs.resourceManager); graphStorage = rhs.graphStorage;
logicalDeviceHdl = rhs.logicalDeviceHdl;
renderpass = rhs.renderpass; renderpass = rhs.renderpass;
framebuffers = std::move(rhs.framebuffers); framebuffers = std::move(rhs.framebuffers);
prereqNodes = std::move(rhs.prereqNodes); prereqNodes = std::move(rhs.prereqNodes);
@ -199,11 +208,11 @@ namespace SHADE
subpasses = std::move(rhs.subpasses); subpasses = std::move(rhs.subpasses);
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping); resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
subpassIndexing = std::move(rhs.subpassIndexing); subpassIndexing = std::move(rhs.subpassIndexing);
ptrToResources = std::move(rhs.ptrToResources);
pipelineLibrary = std::move(rhs.pipelineLibrary); pipelineLibrary = std::move(rhs.pipelineLibrary);
batcher = std::move(rhs.batcher); batcher = std::move(rhs.batcher);
spDescs = std::move(rhs.spDescs); spDescs = std::move(rhs.spDescs);
spDeps = std::move(rhs.spDeps); spDeps = std::move(rhs.spDeps);
nodeComputes = std::move(rhs.nodeComputes);
rhs.renderpass = {}; rhs.renderpass = {};
@ -235,10 +244,10 @@ namespace SHADE
} }
// Add subpass to container and create mapping for it // Add subpass to container and create mapping for it
subpasses.emplace_back(resourceManager->Create<SHSubpass>(GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources)); subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()), &resourceAttachmentMapping));
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u); subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back(); Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(*resourceManager); subpass->Init(*graphStorage->resourceManager);
// Register the SuperBatch // Register the SuperBatch
batcher.RegisterSuperBatch(subpass->GetSuperBatch()); batcher.RegisterSuperBatch(subpass->GetSuperBatch());
@ -246,21 +255,84 @@ namespace SHADE
return subpass; return subpass;
} }
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale/* = 1.0f*/) noexcept
{
// Look for the required resources in the graph
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
nodeComputeResources.reserve(resources.size());
for (auto& resourceName : resources)
{
auto resource = graphStorage->graphResources->at(resourceName);
nodeComputeResources.push_back(resource);
}
// Create the subpass compute with the resources
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources));
nodeComputes.push_back(nodeCompute);
return nodeCompute;
}
/***************************************************************************/
/*!
\brief
This function checks all node computes and adds a subpass to transition
all needed resources to general.
*/
/***************************************************************************/
void SHRenderGraphNode::AddDummySubpassIfNeeded(void) noexcept
{
if (!nodeComputes.empty())
{
// we save the resource names involved
std::unordered_set<std::string> resourcesInvolved;
for (auto& compute : nodeComputes)
{
for (auto& resource : compute->resources)
{
resourcesInvolved.emplace(resource->GetName());
}
}
// insert them all for a subpass to transition them. This subpass is the last subpass
auto dummySubpass = AddSubpass("dummy");
for (auto& resource : resourcesInvolved)
{
dummySubpass->AddGeneralInput(resource);
if (SHVkUtil::IsDepthStencilAttachment(graphStorage->graphResources->at(resource)->GetResourceFormat()))
dummySubpass->AddGeneralDepthOutput(resource);
else
dummySubpass->AddGeneralColorOutput(resource);
}
}
}
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
{ {
frameIndex = (framebuffers.size() > 1) ? frameIndex : 0; uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]); commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
for (uint32_t i = 0; i < subpasses.size(); ++i) for (uint32_t i = 0; i < subpasses.size(); ++i)
{ {
subpasses[i]->Execute(commandBuffer, descPool, frameIndex); subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
// Go to next subpass if not last subpass // Go to next subpass if not last subpass
if (i != subpasses.size() - 1) if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
commandBuffer->NextSubpass(); commandBuffer->NextSubpass();
} }
commandBuffer->EndRenderpass(); commandBuffer->EndRenderpass();
// Execute all subpass computes
for (auto& sbCompute : nodeComputes)
{
sbCompute->Execute(commandBuffer, frameIndex);
}
} }
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
@ -273,10 +345,10 @@ namespace SHADE
} }
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair); Handle<SHVkPipeline> pipeline = pipelineLibrary.GetGraphicsPipeline(vsFsPair);
if (!pipeline) if (!pipeline)
{ {
pipeline = pipelineLibrary.CreateDrawPipeline pipeline = pipelineLibrary.CreateGraphicsPipelines
( (
vsFsPair, vsFsPair,
renderpass, renderpass,
@ -289,7 +361,7 @@ namespace SHADE
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
{ {
batcher.FinaliseBatches(logicalDeviceHdl, descPool, frameIndex); batcher.FinaliseBatches(graphStorage->logicalDevice, descPool, frameIndex);
} }
/***************************************************************************/ /***************************************************************************/

View File

@ -19,6 +19,9 @@ namespace SHADE
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkRenderpass; class SHVkRenderpass;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHGraphicsGlobalData;
class SHRenderGraphStorage;
class SHRenderGraphNodeCompute;
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode> class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
{ {
@ -26,10 +29,9 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
std::shared_ptr<SHResourceHub> resourceManager;
//! For Vulkan object creation //! For Vulkan object creation
Handle<SHVkLogicalDevice> logicalDeviceHdl; //Handle<SHVkLogicalDevice> logicalDeviceHdl;
Handle<SHRenderGraphStorage> graphStorage;
//! Each node will have a renderpass and each renderpass will have its own subpasses. //! Each node will have a renderpass and each renderpass will have its own subpasses.
//! These subpasses will execute sequentially. //! These subpasses will execute sequentially.
@ -63,12 +65,13 @@ namespace SHADE
//! For indexing subpasses //! For indexing subpasses
std::map<std::string, uint32_t> subpassIndexing; std::map<std::string, uint32_t> subpassIndexing;
//! Pointer to resources in the render graph (for getting handle IDs)
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
//! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass //! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
SHPipelineLibrary pipelineLibrary; SHPipelineLibrary pipelineLibrary;
//! Sometimes we want the subpass to do something to the images instead
//! of drawing objects on the image (i.e. compute).
std::vector<Handle<SHRenderGraphNodeCompute>> nodeComputes;
//! Whether or not the node has finished execution //! Whether or not the node has finished execution
bool executed; bool executed;
@ -77,6 +80,7 @@ namespace SHADE
SHBatcher batcher; SHBatcher batcher;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -88,7 +92,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphNode(std::shared_ptr<SHResourceHub> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept; SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept;
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
@ -96,6 +100,9 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept; Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept;
Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale = 1.0f) noexcept;
void AddDummySubpassIfNeeded (void) noexcept;
// TODO: RemoveSubpass() // TODO: RemoveSubpass()
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept; Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;

View File

@ -0,0 +1,109 @@
#include "SHpch.h"
#include "SHRenderGraphNodeCompute.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "SHRenderGraphStorage.h"
#include "SHRenderGraphResource.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
namespace SHADE
{
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale/* = 1.0f*/) noexcept
: computePipeline{}
, pipelineLayout{}
, resources{}
, groupSizeX{0}
, groupSizeY{0}
, numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)}
{
SHPipelineLayoutParams pipelineLayoutParams
{
.shaderModules = {computeShaderModule},
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
};
// Create pipeline layout from parameters
pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout (pipelineLayoutParams);
// Create the compute pipeline
computePipeline = graphStorage->logicalDevice->CreateComputePipeline(pipelineLayout);
// and construct it
computePipeline->ConstructPipeline();
// save the resources
resources = std::move (subpassComputeResources);
//Get the descriptor set layouts required to allocate. We only want the ones for allocate because
//global descriptors are already bound in the main system.
auto const& layouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate();
//Variable counts for the descriptor sets (all should be 1).
std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(layouts.size()) };
std::fill(variableCounts.begin(), variableCounts.end(), 0);
// Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE)
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
{
descSetGroups[i] = graphStorage->descriptorPool->Allocate(layouts, variableCounts);
}
HandleResize();
}
void SHRenderGraphNodeCompute::Execute(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
// bind the compute pipeline
cmdBuffer->BindPipeline(computePipeline);
// bind descriptor sets
cmdBuffer->BindDescriptorSet(descSetGroups[frameIndex], SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, {});
// dispatch compute
cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1);
// TODO: barrier
}
void SHRenderGraphNodeCompute::HandleResize(void) noexcept
{
// Get the layout for the render graph resource. We can index it this way because the container returned is a container of layouts that includes the global ones
auto pipelineDescSetLayouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline()[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE];
// everything below here needs resizing
for (uint32_t frameIndex = 0; frameIndex < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++frameIndex)
{
uint32_t i = 0;
// loop through bindings and write descriptor sets
for (auto& binding : pipelineDescSetLayouts->GetBindings())
{
uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0;
SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, vk::ImageLayout::eGeneral);
descSetGroups[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 });
descSetGroups[frameIndex]->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
++i;
}
}
// Get the group size from the max width and height
uint32_t maxWidth = 0, maxHeight = 0;
for (auto& resource : resources)
{
maxWidth = std::max(resource->GetWidth(), maxWidth);
maxHeight = std::max(resource->GetHeight(), maxHeight);
}
groupSizeX = maxWidth / workGroupSizeX;
groupSizeY = maxHeight / workGroupSizeY;
}
}

View File

@ -0,0 +1,57 @@
#pragma once
#include "Resource/SHHandle.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include <initializer_list>
#include <string>
#include <unordered_set>
namespace SHADE
{
class SHVkPipeline;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool;
class SHVkLogicalDevice;
class SHVkPipelineLayout;
class SHRenderGraphStorage;
class SHRenderGraphResource;
class SHVkShaderModule;
class SHVkCommandBuffer;
class SHRenderGraphNodeCompute
{
private:
static constexpr uint32_t workGroupSizeX = 16;
static constexpr uint32_t workGroupSizeY = 16;
//! To run the dispatch command
Handle<SHVkPipeline> computePipeline;
//! Pipeline layout for the pipeline creation
Handle<SHVkPipelineLayout> pipelineLayout;
//! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> descSetGroups;
//! vector of resources needed by the subpass compute
std::vector<Handle<SHRenderGraphResource>> resources;
//! X dimension work group size. Should scale with resource size.
uint32_t groupSizeX;
//! Y dimension work group size
uint32_t groupSizeY;
float numWorkGroupScale;
public:
SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale = 1.0f) noexcept;
void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept;
friend class SHRenderGraph;
friend class SHRenderGraphNode;
};
}

View File

@ -5,6 +5,7 @@
#include "Graphics/Images/SHVkImageView.h" #include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/SHVkUtil.h" #include "Graphics/SHVkUtil.h"
#include "SHRenderGraphStorage.h"
namespace SHADE namespace SHADE
{ {
@ -45,9 +46,8 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
: logicalDevice {logicalDevice} : graphStorage{renderGraphStorage}
, swapchain{ swapchain }
, resourceTypeFlags{ } , resourceTypeFlags{ }
, resourceFormat{ format } , resourceFormat{ format }
, images{} , images{}
@ -66,7 +66,7 @@ namespace SHADE
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
{ {
.viewType = vk::ImageViewType::e2D, .viewType = vk::ImageViewType::e2D,
.format = swapchain->GetSurfaceFormatKHR().format, .format = graphStorage->swapchain->GetSurfaceFormatKHR().format,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor, .imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0, .baseMipLevel = 0,
.mipLevelCount = 1, .mipLevelCount = 1,
@ -75,13 +75,13 @@ namespace SHADE
}; };
// We want an image handle for every swapchain image // We want an image handle for every swapchain image
images.resize(swapchain->GetNumImages()); images.resize(graphStorage->swapchain->GetNumImages());
imageViews.resize(swapchain->GetNumImages()); imageViews.resize(graphStorage->swapchain->GetNumImages());
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i) for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
{ {
images[i] = swapchain->GetSwapchainImage(i); images[i] = graphStorage->swapchain->GetSwapchainImage(i);
imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails); imageViews[i] = images[i]->CreateImageView(graphStorage->logicalDevice, images[i], viewDetails);
} }
} }
else // if swapchain image resource else // if swapchain image resource
@ -117,6 +117,9 @@ namespace SHADE
usage |= vk::ImageUsageFlagBits::eInputAttachment; usage |= vk::ImageUsageFlagBits::eInputAttachment;
usage |= vk::ImageUsageFlagBits::eSampled; usage |= vk::ImageUsageFlagBits::eSampled;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::STORAGE:
usage |= vk::ImageUsageFlagBits::eStorage;
break;
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT: case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
{ {
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. "); SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
@ -126,7 +129,7 @@ namespace SHADE
} }
// The resource is not a swapchain image, just use the first slot of the vector // The resource is not a swapchain image, just use the first slot of the vector
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags)); images.push_back(graphStorage->logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
// prepare image view details // prepare image view details
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
@ -141,7 +144,7 @@ namespace SHADE
}; };
// just 1 image view created // just 1 image view created
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails)); imageViews.push_back(images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails));
} }
} }
@ -166,7 +169,7 @@ namespace SHADE
, height{ rhs.height } , height{ rhs.height }
, mipLevels{ rhs.mipLevels } , mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags } , imageAspectFlags{ rhs.imageAspectFlags }
, swapchain {rhs.swapchain} , graphStorage{rhs.graphStorage}
{ {
} }
@ -198,7 +201,7 @@ namespace SHADE
height = rhs.height; height = rhs.height;
mipLevels = rhs.mipLevels; mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags; imageAspectFlags = rhs.imageAspectFlags;
swapchain = rhs.swapchain; graphStorage = rhs.graphStorage;
return *this; return *this;
} }
@ -247,7 +250,7 @@ namespace SHADE
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
{ {
.viewType = vk::ImageViewType::e2D, .viewType = vk::ImageViewType::e2D,
.format = swapchain->GetSurfaceFormatKHR().format, .format = graphStorage->swapchain->GetSurfaceFormatKHR().format,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor, .imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0, .baseMipLevel = 0,
.mipLevelCount = 1, .mipLevelCount = 1,
@ -255,9 +258,9 @@ namespace SHADE
.layerCount = 1, .layerCount = 1,
}; };
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i) for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
{ {
images[i] = swapchain->GetSwapchainImage(i); images[i] = graphStorage->swapchain->GetSwapchainImage(i);
imageViews[i]->ViewNewImage(images[i], viewDetails); imageViews[i]->ViewNewImage(images[i], viewDetails);
} }
} }
@ -308,6 +311,7 @@ namespace SHADE
return resourceFormat; return resourceFormat;
} }
uint32_t SHRenderGraphResource::GetWidth(void) const noexcept uint32_t SHRenderGraphResource::GetWidth(void) const noexcept
{ {
return width; return width;
@ -323,4 +327,19 @@ namespace SHADE
return imageViews [index]; return imageViews [index];
} }
Handle<SHVkImage> SHRenderGraphResource::GetImage(uint32_t index /*= NON_SWAPCHAIN_RESOURCE_INDEX*/) const noexcept
{
return images[index];
}
uint8_t SHRenderGraphResource::GetMipLevels(void) const noexcept
{
return mipLevels;
}
std::string SHRenderGraphResource::GetName(void) const noexcept
{
return resourceName;
}
} }

View File

@ -15,6 +15,7 @@ namespace SHADE
class SHVkSwapchain; class SHVkSwapchain;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkBuffer; class SHVkBuffer;
class SHRenderGraphStorage;
static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0; static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
@ -24,11 +25,8 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// for creation/recreation //! Storage from the render graph
Handle<SHVkLogicalDevice> logicalDevice; Handle<SHRenderGraphStorage> graphStorage;
// for creation/recreation
Handle<SHVkSwapchain> swapchain;
//! Name of the resource //! Name of the resource
std::string resourceName; std::string resourceName;
@ -69,7 +67,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept; SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept; ~SHRenderGraphResource(void) noexcept;
@ -88,8 +86,13 @@ namespace SHADE
uint32_t GetWidth (void) const noexcept; uint32_t GetWidth (void) const noexcept;
uint32_t GetHeight (void) const noexcept; uint32_t GetHeight (void) const noexcept;
Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept; Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
uint8_t GetMipLevels (void) const noexcept;
std::string GetName (void) const noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHSubpass;
friend class SHRenderGraphNodeCompute;
}; };
} }

View File

@ -0,0 +1,43 @@
#pragma once
#include "Resource/SHHandle.h"
#include <memory>
namespace SHADE
{
class SHVkLogicalDevice;
class SHVkSwapchain;
class SHGraphicsGlobalData;
class SHVkDescriptorPool;
class SHRenderGraphResource;
class SHRenderGraphStorage
{
//! Logical device for creation of vulkan objects
Handle<SHVkLogicalDevice> logicalDevice;
//! swapchain handle
Handle<SHVkSwapchain> swapchain;
//! Resource manager for creation of objects
std::shared_ptr<SHResourceHub> resourceManager;
//! Descriptor pool for the descriptor sets to be created in the subpasses
Handle<SHVkDescriptorPool> descriptorPool;
//! For accessing resources anywhere in the graph
Handle<std::unordered_map<std::string, Handle<SHRenderGraphResource>>> graphResources;
//SHRenderGraphStorage(void) noexcept;
//SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept;
//SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept;
friend class SHRenderGraph;
friend class SHRenderGraphNode;
friend class SHSubpass;
friend class SHRenderGraphResource;
friend class SHRenderGraphNodeCompute;
};
}

View File

@ -4,6 +4,13 @@
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "SHRenderGraphNode.h" #include "SHRenderGraphNode.h"
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "SHRenderGraphNode.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Images/SHVkSampler.h"
#include "SHRenderGraphResource.h"
namespace SHADE namespace SHADE
{ {
@ -23,15 +30,16 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHSubpass::SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept SHSubpass::SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept
: resourceAttachmentMapping{ mapping } : resourceAttachmentMapping{ mapping }
, ptrToResources{ resources }
, parentNode{ parent } , parentNode{ parent }
, subpassIndex{ index } , subpassIndex{ index }
, superBatch{} , superBatch{}
, colorReferences{} , colorReferences{}
, depthReferences{} , depthReferences{}
, inputReferences{} , inputReferences{}
, graphStorage{ renderGraphStorage }
, inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
{ {
} }
@ -54,9 +62,14 @@ namespace SHADE
, depthReferences{ std::move(rhs.depthReferences) } , depthReferences{ std::move(rhs.depthReferences) }
, inputReferences{ std::move(rhs.inputReferences) } , inputReferences{ std::move(rhs.inputReferences) }
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping } , resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
, ptrToResources{ rhs.ptrToResources }
, descriptorSetLayout{ rhs.descriptorSetLayout } , descriptorSetLayout{ rhs.descriptorSetLayout }
, exteriorDrawCalls{ std::move (rhs.exteriorDrawCalls) } , exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
, graphStorage{ rhs.graphStorage }
, inputNames{ std::move(rhs.inputNames) }
, inputImageDescriptors{ std::move(rhs.inputImageDescriptors) }
, inputDescriptorLayout{ rhs.inputDescriptorLayout }
, inputSamplers{ rhs.inputSamplers }
{ {
} }
@ -84,9 +97,13 @@ namespace SHADE
depthReferences = std::move(rhs.depthReferences); depthReferences = std::move(rhs.depthReferences);
inputReferences = std::move(rhs.inputReferences); inputReferences = std::move(rhs.inputReferences);
resourceAttachmentMapping = rhs.resourceAttachmentMapping; resourceAttachmentMapping = rhs.resourceAttachmentMapping;
ptrToResources = rhs.ptrToResources;
descriptorSetLayout = rhs.descriptorSetLayout; descriptorSetLayout = rhs.descriptorSetLayout;
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls); exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
graphStorage = rhs.graphStorage;
inputNames = std::move(rhs.inputNames);
inputImageDescriptors = std::move(rhs.inputImageDescriptors);
inputDescriptorLayout = rhs.inputDescriptorLayout;
inputSamplers = rhs.inputSamplers;
return *this; return *this;
} }
@ -105,7 +122,12 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
{ {
colorReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal }); colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
}
void SHSubpass::AddGeneralColorOutput(std::string resourceToReference) noexcept
{
colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
} }
/***************************************************************************/ /***************************************************************************/
@ -142,7 +164,13 @@ namespace SHADE
//Invalid //Invalid
return; return;
} }
depthReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), imageLayout }); depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), imageLayout });
}
void SHSubpass::AddGeneralDepthOutput(std::string resourceToReference) noexcept
{
depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
} }
/***************************************************************************/ /***************************************************************************/
@ -159,7 +187,14 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHSubpass::AddInput(std::string resourceToReference) noexcept void SHSubpass::AddInput(std::string resourceToReference) noexcept
{ {
inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal }); inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
inputNames.push_back(resourceToReference);
}
void SHSubpass::AddGeneralInput(std::string resourceToReference) noexcept
{
inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
} }
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
@ -175,6 +210,12 @@ namespace SHADE
{ {
drawCall(commandBuffer); drawCall(commandBuffer);
} }
}
void SHSubpass::HandleResize(void) noexcept
{
UpdateWriteDescriptors();
} }
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
@ -188,6 +229,152 @@ namespace SHADE
} }
void SHSubpass::CreateInputDescriptors(void) noexcept
{
if (inputNames.empty())
return;
std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
for (auto& input : inputReferences)
{
SHVkDescriptorSetLayout::Binding newBinding
{
.Type = (input.layout == vk::ImageLayout::eShaderReadOnlyOptimal) ? vk::DescriptorType::eInputAttachment : vk::DescriptorType::eStorageImage,
.Stage = vk::ShaderStageFlagBits::eFragment,
.BindPoint = static_cast<uint32_t>(bindings.size()),
.DescriptorCount = 1,
.flags = {},
};
bindings.push_back(newBinding);
}
// We build a new descriptor set layout to store our images
inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings);
// we store a sampler if its an input attachment. if it is storage image, no need sampler, store an empty handle.
for (uint32_t i = 0; i < bindings.size(); ++i)
{
if (bindings[i].Type == vk::DescriptorType::eInputAttachment)
{
auto newSampler = graphStorage->logicalDevice->CreateSampler(SHVkSamplerParams
{
.minFilter = vk::Filter::eLinear,
.magFilter = vk::Filter::eLinear,
.addressMode = vk::SamplerAddressMode::eRepeat,
.mipmapMode = vk::SamplerMipmapMode::eLinear,
.minLod = -1000,
.maxLod = 1000
}
);
inputSamplers.push_back(newSampler);
}
else
{
inputSamplers.push_back({});
}
}
//// maybe do this in handle resize?
//UpdateWriteDescriptors();
}
void SHSubpass::UpdateWriteDescriptors(void) noexcept
{
if (inputNames.empty())
return;
auto const& bindings = inputDescriptorLayout->GetBindings();
std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(bindings.size()) };
std::fill (variableCounts.begin(), variableCounts.end(), 0u);
// For every frame's descriptor set
for (auto& group : inputImageDescriptors)
{
if (group)
group.Free();
group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts);
uint32_t i = 0;
for (auto& binding : bindings)
{
// get the resource
auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]);
// If resource is swapchain image, get the correct image, if not just get 0.
uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
// layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL
vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
// Update descriptor sets
auto args = std::make_tuple(resource->GetImageView(viewIndex), inputSamplers[i], descriptorLayout);
group->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, std::span{&args, 1});
group->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
}
++i;
}
}
//void SHSubpass::InitComputeBarriers(void) noexcept
//{
// std::unordered_set <uint64_t> handleBarriers{};
// // we will have swapchainNumImages vectors of vector of barriers
// subpassComputeBarriers.resize(graphStorage->swapchain->GetNumImages());
// for (auto sbCompute : subpassComputes)
// {
// // for every resource the subpass compute is using
// for (auto resource : sbCompute->resources)
// {
// // Get the resource handle
// uint64_t resourceRaw = resource.GetId().Raw;
// // if the barrier is not registered
// if (!handleBarriers.contains(resourceRaw))
// {
// // If the resource is a swapchain image
// bool isSwapchainImage = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT));
// for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
// {
// // if swapchain image, we want the index of the swapchain image, if not take base image
// uint32_t imageIndex = isSwapchainImage ? i : 0;
// // Prepare image barrier
// vk::ImageMemoryBarrier imageBarrier
// {
// .oldLayout = colorReferences[resourceAttachmentMapping->at(resource.GetId().Raw)].layout,
// .newLayout = vk::ImageLayout::eGeneral,
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
// .image = resource->GetImage(imageIndex)->GetVkImage(),
// .subresourceRange =
// {
// .aspectMask = resource->imageAspectFlags,
// .levelCount = resource->GetMipLevels(),
// .baseArrayLayer = 0,
// .layerCount = 1
// }
// };
// // push the barrier
// subpassComputeBarriers[i].push_back(imageBarrier);
// }
// // Image transition registered
// handleBarriers.emplace(resourceRaw);
// }
// }
// }
//}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -14,7 +14,11 @@ namespace SHADE
class SHRenderGraphResource; class SHRenderGraphResource;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHRenderGraphStorage;
class SHVkShaderModule;
class SHVkSampler;
class SH_API SHSubpass : public ISelfHandle<SHSubpass> class SH_API SHSubpass : public ISelfHandle<SHSubpass>
{ {
@ -22,6 +26,8 @@ namespace SHADE
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
Handle<SHRenderGraphStorage> graphStorage;
//! The index of the subpass in the render graph //! The index of the subpass in the render graph
uint32_t subpassIndex; uint32_t subpassIndex;
@ -43,11 +49,26 @@ namespace SHADE
//! Input attachments //! Input attachments
std::vector<vk::AttachmentReference> inputReferences; std::vector<vk::AttachmentReference> inputReferences;
//! This is mainly for when we want to retrieve resources using names.
std::vector<std::string> inputNames;
//! For getting attachment reference indices using handles //! For getting attachment reference indices using handles
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping; std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
//! Pointer to resources in the render graph (for getting handle IDs) //! Descriptor set group to hold the images for input
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources; std::vector<Handle<SHVkDescriptorSetGroup>> inputImageDescriptors;
//! Descriptor set layout for allocating descriptor set for inputs
Handle<SHVkDescriptorSetLayout> inputDescriptorLayout;
std::vector<Handle<SHVkSampler>> inputSamplers;
////! subpass compute image barriers. We do this because every frame has a different
////! swapchain image. If the resource we want to transition is not a swapchain image,
////! we duplicate the barrier anyway, not much memory wasted. ;)
//std::vector<std::vector<vk::ImageMemoryBarrier>> subpassComputeBarriers{};
//! Sometimes there exists entities that we want to render onto a render target //! Sometimes there exists entities that we want to render onto a render target
//! but don't want it to come from the batching system. An example would be ImGUI. //! but don't want it to come from the batching system. An example would be ImGUI.
@ -62,7 +83,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHSubpass(Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept; SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept;
SHSubpass(SHSubpass&& rhs) noexcept; SHSubpass(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept; SHSubpass& operator=(SHSubpass&& rhs) noexcept;
@ -71,15 +92,23 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// Preparation functions // Preparation functions
void AddColorOutput(std::string resourceToReference) noexcept; void AddColorOutput(std::string resourceToReference) noexcept;
void AddGeneralColorOutput(std::string resourceToReference) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept; void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
void AddGeneralDepthOutput(std::string resourceToReference) noexcept;
void AddInput(std::string resourceToReference) noexcept; void AddInput(std::string resourceToReference) noexcept;
void AddGeneralInput (std::string resourceToReference) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
// Runtime functions // Runtime functions
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept; void HandleResize (void) noexcept;
void Init(SHResourceHub& resourceManager) noexcept; void Init(SHResourceHub& resourceManager) noexcept;
//void InitComputeBarriers (void) noexcept;
void CreateInputDescriptors (void) noexcept;
void UpdateWriteDescriptors (void) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -91,5 +120,6 @@ namespace SHADE
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHSubpass;
}; };
} }

View File

@ -1,23 +0,0 @@
#include "SHpch.h"
#include "SHSubpassCompute.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
namespace SHADE
{
SHSubpassCompute::SHSubpassCompute(Handle<SHVkPipeline> inPipeline, Handle<SHVkDescriptorPool> descPool) noexcept
: pipeline {inPipeline}
{
// Get the descriptor set layouts required to allocate. we will bind a different pipeline layout, one that includes the layout for global.
auto const& layouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate();
// Variable counts for the descriptor sets (all should be 1).
std::vector<uint32_t> variableCounts{static_cast<uint32_t>(layouts.size())};
std::fill (variableCounts.begin(), variableCounts.end(), 0);
// Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE)
descPool->Allocate(layouts, variableCounts);
}
}

View File

@ -1,25 +0,0 @@
#pragma once
#include <Resource/SHHandle.h>
namespace SHADE
{
class SHVkPipeline;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool;
class SHSubpassCompute
{
private:
//! To run the dispatch command
Handle<SHVkPipeline> pipeline;
//! Descriptor set group
Handle<SHVkDescriptorSetGroup> descSetGroup;
public:
SHSubpassCompute (Handle<SHVkPipeline> inPipeline, Handle<SHVkDescriptorPool> descPool) noexcept;
};
}

View File

@ -55,6 +55,21 @@ namespace SHADE
return 0; return 0;
} }
vk::PipelineBindPoint SHVkUtil::GetPipelineBindPointFromType(SH_PIPELINE_TYPE pipelineType) noexcept
{
switch (pipelineType)
{
case SH_PIPELINE_TYPE::GRAPHICS:
return vk::PipelineBindPoint::eGraphics;
case SH_PIPELINE_TYPE::COMPUTE:
return vk::PipelineBindPoint::eCompute;
case SH_PIPELINE_TYPE::RAY_TRACING:
return vk::PipelineBindPoint::eRayTracingKHR;
default:
return vk::PipelineBindPoint::eGraphics;
}
}
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage) void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
{ {
if (bufferHandle) if (bufferHandle)

View File

@ -4,6 +4,7 @@
#include "SHVulkanIncludes.h" #include "SHVulkanIncludes.h"
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "Graphics/Pipeline/SHPipelineType.h"
namespace SHADE namespace SHADE
{ {
@ -24,6 +25,7 @@ namespace SHADE
static bool IsDepthStencilAttachment (vk::Format format) noexcept; static bool IsDepthStencilAttachment (vk::Format format) noexcept;
static bool IsBlendCompatible (vk::Format format) noexcept; static bool IsBlendCompatible (vk::Format format) noexcept;
static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept; static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept;
static vk::PipelineBindPoint GetPipelineBindPointFromType (SH_PIPELINE_TYPE pipelineType) noexcept;
/***********************************************************************************/ /***********************************************************************************/
/*! /*!

View File

@ -177,6 +177,9 @@ namespace SHADE
return vk::DescriptorType::eStorageBufferDynamic; return vk::DescriptorType::eStorageBufferDynamic;
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return vk::DescriptorType::eInputAttachment; return vk::DescriptorType::eInputAttachment;
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE:
return vk::DescriptorType::eStorageImage;
break;
default: default:
return vk::DescriptorType::eCombinedImageSampler; return vk::DescriptorType::eCombinedImageSampler;
break; break;

View File

@ -20,6 +20,10 @@ namespace SHADE
/* Static defines */ /* Static defines */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
bool SHInputManager::controllerInUse = false;
std::map<std::string, SHInputManager::SHLogicalBindingData> SHInputManager::bindings;
unsigned SHInputManager::keyCount = 0; unsigned SHInputManager::keyCount = 0;
bool SHInputManager::keys[MAX_KEYS]; bool SHInputManager::keys[MAX_KEYS];
bool SHInputManager::keysLast[MAX_KEYS]; bool SHInputManager::keysLast[MAX_KEYS];
@ -41,6 +45,60 @@ namespace SHADE
int SHInputManager::mouseWheelVerticalDelta = 0; int SHInputManager::mouseWheelVerticalDelta = 0;
int SHInputManager::mouseWheelVerticalDeltaPoll = 0; int SHInputManager::mouseWheelVerticalDeltaPoll = 0;
unsigned char SHInputManager::controllersConnectedCount = 0;
unsigned SHInputManager::controllersInputCount[XUSER_MAX_COUNT];
unsigned SHInputManager::controllersButtonCount[XUSER_MAX_COUNT];
short SHInputManager::controllers[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
short SHInputManager::controllersLast[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
double SHInputManager::controllersHeldTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
double SHInputManager::controllersReleasedTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//Internal helper function for splitting between inputs
bool SHInputManager::controllerConsideredHeld(size_t inputIdx, short value) noexcept
{
if (inputIdx >= MAX_CONTROLLER_INPUT) return false; //Bounds check
else
{
if (inputIdx < NUM_CONTROLLER_BUTTON)
{
return static_cast<bool>(value);
}
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER)
{
return (value > XINPUT_GAMEPAD_TRIGGER_THRESHOLD);
}
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER + NUM_CONTROLLER_TRIGGER)
{
return (std::abs(value) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
}
else
{
return (std::abs(value) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
}
}
}
//Internal helper function for getting normalised input value
double SHInputManager::controllerNormalisedValue(size_t inputIdx, short value) noexcept
{
if (inputIdx >= MAX_CONTROLLER_INPUT) return 0.0; //Bounds check
else
{
if (inputIdx < NUM_CONTROLLER_BUTTON)
{
return static_cast<double>(value);
}
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER) //8-bit triggers, 0 to 255
{
return static_cast<double>(value) / static_cast<double>(UCHAR_MAX);
}
else //16-bit thumbsticks, -32768 to 32767
{
return static_cast<double>(value) / static_cast<double>(SHRT_MAX);
}
}
}
void SHInputManager::UpdateInput(double dt) noexcept void SHInputManager::UpdateInput(double dt) noexcept
{ {
//Keyboard and Mouse Buttons//////////////////////////////////////////////// //Keyboard and Mouse Buttons////////////////////////////////////////////////
@ -120,6 +178,273 @@ namespace SHADE
mouseWheelVerticalDelta = 0; mouseWheelVerticalDelta = 0;
mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll; mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll;
mouseWheelVerticalDeltaPoll = 0; mouseWheelVerticalDeltaPoll = 0;
//Controllers//////////////////////////////////////////////////////////////
controllersConnectedCount = 0;
//Set last controller states
memcpy(controllersLast, controllers, sizeof(controllers));
//Reset controller states
SecureZeroMemory(&controllers, sizeof(controllers));
//https://learn.microsoft.com/en-us/windows/win32/xinput/getting-started-with-xinput#getting-controller-state
for (DWORD c = 0; c < XUSER_MAX_COUNT; ++c)
{
controllersInputCount[c] = 0;
controllersButtonCount[c] = 0;
XINPUT_STATE state;
SecureZeroMemory(&state, sizeof(XINPUT_STATE));
//Get the state of controller from XInput
DWORD result = XInputGetState(c, &state);
//Write gamepad data
if (result == ERROR_SUCCESS)
{
++controllersConnectedCount;
//DIGITAL BUTTONS///////////////////////////////////////
//DPAD UP
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_UP)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_UP)] = 0;
}
//DPAD DOWN
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_DOWN)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_DOWN)] = 0;
}
//DPAD LEFT
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_LEFT)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_LEFT)] = 0;
}
//DPAD RIGHT
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_RIGHT)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_RIGHT)] = 0;
}
//START
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::START)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::START)] = 0;
}
//BACK
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::BACK)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::BACK)] = 0;
}
//LEFT THUMBSTICK BUTTON
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK)] = 0;
}
//RIGHT THUMBSTICK BUTTON
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK)] = 0;
}
//LEFT SHOULDER BUTTON
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_SHOULDER)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_SHOULDER)] = 0;
}
//RIGHT SHOULDER BUTTON
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_SHOULDER)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_SHOULDER)] = 0;
}
//A
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::A)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::A)] = 0;
}
//B
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::B)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::B)] = 0;
}
//X
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::X)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::X)] = 0;
}
//Y
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y)
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::Y)] = 1;
++controllersInputCount[c];
++controllersButtonCount[c];
}
else
{
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::Y)] = 0;
}
//8 BIT VALUES (0 - 255)///////////////////////////////////
//LEFT TRIGGER
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_TRIGGER)] = state.Gamepad.bLeftTrigger;
if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
{
++controllersInputCount[c]; //Registered as held
}
//RIGHT TRIGGER
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_TRIGGER)] = state.Gamepad.bRightTrigger;
if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
{
++controllersInputCount[c]; //Registered as held
}
//16 BIT VALUES (0 - 65535)////////////////////////////////
//LEFT THUMBSTICK X
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK_X)] = state.Gamepad.sThumbLX;
if (std::abs(state.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
++controllersInputCount[c];
}
//LEFT THUMBSTICK Y
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK_Y)] = state.Gamepad.sThumbLY;
if (std::abs(state.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
++controllersInputCount[c];
}
//RIGHT THUMBSTICK X
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK_X)] = state.Gamepad.sThumbRX;
if (std::abs(state.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
++controllersInputCount[c];
}
//RIGHT THUMBSTICK Y
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK_Y)] = state.Gamepad.sThumbRY;
if (std::abs(state.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
++controllersInputCount[c];
}
}
//Timers and updating if controller is presently in use
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
{
if (controllerConsideredHeld(i, controllers[c][i])) //Considered on
{
controllerInUse = true;
if (!controllerConsideredHeld(i, controllersLast[c][i])) //Just on
{
controllersHeldTime[c][i] = 0.0; //Reset timer
}
controllersHeldTime[c][i] += dt; //Tick up
}
else //Considered off
{
if (controllerConsideredHeld(i, controllersLast[c][i])) //Just off
{
controllersReleasedTime[c][i] = 0.0; //Reset timer
}
controllersReleasedTime[c][i] += dt; //Tick up
}
}
}
} }
bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept
@ -161,4 +486,336 @@ namespace SHADE
return false; return false;
} }
//Any controller input being held
//For analog, this means going being deadzone values
bool SHInputManager::AnyControllerInput(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
{
if (controllerConsideredHeld(i, controllers[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerInputDown(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
{
if (controllerConsideredHeld(i, controllers[cNum][i]) && !controllerConsideredHeld(i, controllersLast[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerInputUp(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
{
if (!controllerConsideredHeld(i, controllers[cNum][i]) && controllerConsideredHeld(i, controllersLast[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerButton(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
{
if (controllerConsideredHeld(i, controllers[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerButtonDown(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
{
if (controllerConsideredHeld(i, controllers[cNum][i]) && !controllerConsideredHeld(i, controllersLast[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
bool SHInputManager::AnyControllerButtonUp(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
{
if (!controllerConsideredHeld(i, controllers[cNum][i]) && controllerConsideredHeld(i, controllersLast[cNum][i]))
{
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
return true;
}
}
return false;
}
//Only get of largest magnitude
double SHInputManager::GetBindingAxis(std::string bindingName, size_t cNum) noexcept
{
//Over keycodes, prioritise positive
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKey(k)) return 1.0;
}
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKey(k)) return -1.0;
}
double largestMagnitude = 0.0;
//Over controllerCodes
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
double newValue = 0.0;
if (GetControllerInput(c, &newValue, nullptr, nullptr, cNum))
if (std::abs(newValue) > std::abs(largestMagnitude)) largestMagnitude = newValue;
}
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
double newValue = 0.0;
if (GetControllerInput(c, &newValue, nullptr, nullptr, cNum))
if (std::abs(newValue) > std::abs(largestMagnitude)) largestMagnitude = -newValue;
}
return largestMagnitude;
}
bool SHInputManager::GetBindingPositiveButton(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKey(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingNegativeButton(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKey(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingPositiveButtonDown(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKeyDown(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInputDown(c, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingNegativeButtonDown(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKeyDown(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInputDown(c, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingPositiveButtonUp(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKeyUp(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInputUp(c, nullptr, cNum)) return true;
}
return false;
}
bool SHInputManager::GetBindingNegativeButtonUp(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return false;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKeyUp(k)) return true;
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInputUp(c, nullptr, cNum)) return true;
}
return false;
}
//Fetches longest hold time
double SHInputManager::GetBindingPositiveHeldTime(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
double maxHeldTime = 0.0;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKeyHeldTime(k) > maxHeldTime) maxHeldTime = GetKeyHeldTime(k);
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInputHeldTime(c, cNum) > maxHeldTime) maxHeldTime = GetControllerInputHeldTime(c);
}
return maxHeldTime;
}
double SHInputManager::GetBindingNegativeHeldTime(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
double maxHeldTime = 0.0;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKeyHeldTime(k) > maxHeldTime) maxHeldTime = GetKeyHeldTime(k);
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInputHeldTime(c, cNum) > maxHeldTime) maxHeldTime = GetControllerInputHeldTime(c);
}
return maxHeldTime;
}
//Fetches shortest release time
double SHInputManager::GetBindingPositiveReleasedTime(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
double minReleaseTime = _HUGE_ENUF;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
{
if (GetKeyReleasedTime(k) < minReleaseTime) minReleaseTime = GetKeyReleasedTime(k);
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
{
if (GetControllerInputReleasedTime(c, cNum) < minReleaseTime) minReleaseTime = GetControllerInputReleasedTime(c);
}
return minReleaseTime;
}
double SHInputManager::GetBindingNegativeReleasedTime(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
double minReleaseTime = _HUGE_ENUF;
//Over keycodes
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
{
if (GetKeyReleasedTime(k) < minReleaseTime) minReleaseTime = GetKeyReleasedTime(k);
}
//Over controller buttons
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
{
if (GetControllerInputReleasedTime(c, cNum) < minReleaseTime) minReleaseTime = GetControllerInputReleasedTime(c);
}
return minReleaseTime;
}
//Only for mouse movement
//Get largest delta
double SHInputManager::GetBindingMouseVelocity(std::string bindingName, size_t cNum) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0.0;
//Mouse velocity
double velX = 0.0;
double velY = 0.0;
GetMouseVelocity(&velX, &velY);
return bindings[bindingName].mouseXPositiveMultiplier * velX + bindings[bindingName].mouseYPositiveMultiplier * velY;
}
} //namespace SHADE } //namespace SHADE

View File

@ -10,9 +10,12 @@
*********************************************************************/ *********************************************************************/
#pragma once #pragma once
//#include <Xinput.h> #include <Xinput.h>
//#include "../../SHADE_Managed/src/SHpch.h" #include <map>
#include <set>
#include "../../SHADE_Managed/src/SHpch.h"
#include "SH_API.h" #include "SH_API.h"
#pragma comment(lib, "xinput.lib")
namespace SHADE namespace SHADE
{ {
@ -268,6 +271,58 @@ namespace SHADE
OEM_CLEAR OEM_CLEAR
}; };
enum class SH_CONTROLLERCODE
{
//Digital
DPAD_UP,
DPAD_DOWN,
DPAD_LEFT,
DPAD_RIGHT,
START,
BACK,
LEFT_THUMBSTICK,
RIGHT_THUMBSTICK,
LEFT_SHOULDER,
RIGHT_SHOULDER,
A,
B,
X,
Y,
//1 Byte Unsigned Analog
LEFT_TRIGGER,
RIGHT_TRIGGER,
//2 Byte Signed Analog
LEFT_THUMBSTICK_X,
LEFT_THUMBSTICK_Y,
RIGHT_THUMBSTICK_X,
RIGHT_THUMBSTICK_Y
};
private:
/*------------------------------------------------------------------------*/
/* Struct for logical bindings */
/*------------------------------------------------------------------------*/
struct SH_API SHLogicalBindingData
{
//Key codes mapped to positive
std::set<SH_KEYCODE> positiveKeyCodes;
//Key codes mapped to negative
std::set<SH_KEYCODE> negativeKeyCodes;
//Controller Codes mapped to positive
std::set<SH_CONTROLLERCODE> positiveControllerCodes;
//Controller Codes mapped to negative
std::set<SH_CONTROLLERCODE> negativeControllerCodes;
//Mouse movement mapped to axes?
double mouseXPositiveMultiplier;
double mouseYPositiveMultiplier;
};
public: public:
//Updates current state of the input, with dt to be fetched from FRC //Updates current state of the input, with dt to be fetched from FRC
//TODO should dt be fixed or variable? //TODO should dt be fixed or variable?
@ -392,7 +447,7 @@ namespace SHADE
keysToggleLast[static_cast<int>(key)]); keysToggleLast[static_cast<int>(key)]);
} }
//Mouse///////////// //Mouse/////////////////////////////////////////////////////
//Get the mouse location with respect to the screen //Get the mouse location with respect to the screen
static inline void GetMouseScreenPosition (int* x = nullptr, static inline void GetMouseScreenPosition (int* x = nullptr,
@ -428,7 +483,95 @@ namespace SHADE
return mouseWheelVerticalDelta; return mouseWheelVerticalDelta;
} }
//GET INPUT TIMINGS/////////////////////////////////////////////////////////// /*------------------------------------------------------------------------*/
/* Input state accessors (KB & M) */
/*------------------------------------------------------------------------*/
//How many controller inputs of any kind are being used now
static inline unsigned GetControllerInputCount(size_t cNum = 0) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0;
return controllersInputCount[cNum];
}
//How many controller buttons are being pressed now
//Subtract from getControllerInputCount() for analog triggers / thumbsticks
static inline unsigned GetControllerButtonCount(size_t cNum = 0) noexcept
{
if (cNum >= XUSER_MAX_COUNT) return 0;
return controllersButtonCount[cNum];
}
//Any controller input being held
//For analog, this means going being deadzone values
//controllerNum should be between 0 and 3
static bool AnyControllerInput(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any controller input activated in THIS FRAME ONLY
//For analog, this means going being deadzone values
//controllerNum should be between 0 and 3
static bool AnyControllerInputDown(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any controller input deactivated in THIS FRAME ONLY
//For analog, this means going below deadzone values
//controllerNum should be between 0 and 3
static bool AnyControllerInputUp(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any DIGITAL controller buttons being held
//controllerNum should be between 0 and 3
static bool AnyControllerButton(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any DIGITAL controller button activated in THIS FRAME ONLY
//controllerNum should be between 0 and 3
static bool AnyControllerButtonDown(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//Any DIGITAL controller button deactivated in THIS FRAME ONLY
//controllerNum should be between 0 and 3
static bool AnyControllerButtonUp(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
//If controller input is being held in the current frame
//normalisedValue is the value of the input between 0 and 1, relevant for trigger and thumbstick data
//controllerNum should be between 0 and 3
static inline bool GetControllerInput(SH_CONTROLLERCODE input,
double* normalisedValue = nullptr,
double* heldTime = nullptr,
double* releasedTime = nullptr,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return false;
if (normalisedValue) *normalisedValue = controllerNormalisedValue(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]);
if (heldTime) *heldTime = controllersHeldTime[controllerNum][static_cast<size_t>(input)];
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
return controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]);
}
//If controller input was considered to be held down in THIS FRAME ONLY
//controllerNum should be between 0 and 3
static inline bool GetControllerInputDown(SH_CONTROLLERCODE input,
double* releasedTime = nullptr,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return false;
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
return (controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]) &&
!controllerConsideredHeld(static_cast<size_t>(input), controllersLast[controllerNum][static_cast<size_t>(input)]));
}
//If controller input was considered to be released in THIS FRAME ONLY
//controllerNum should be between 0 and 3
static inline bool GetControllerInputUp(SH_CONTROLLERCODE input,
double* releasedTime = nullptr,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return false;
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
return (!controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]) &&
controllerConsideredHeld(static_cast<size_t>(input), controllersLast[controllerNum][static_cast<size_t>(input)]));
}
/*------------------------------------------------------------------------*/
/* Timing accessors */
/*------------------------------------------------------------------------*/
//Keyboard///////////// //Keyboard/////////////
@ -456,6 +599,191 @@ namespace SHADE
return keysToggleOffTime[static_cast<int>(key)]; return keysToggleOffTime[static_cast<int>(key)];
} }
//Controller//////////////////////
//How long has this controller input been considered to be held down for
static inline double GetControllerInputHeldTime(SH_CONTROLLERCODE code,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return 0.0;
return controllersHeldTime[controllerNum][static_cast<size_t>(code)];
}
//How long has this controller input been considered to be released for
static inline double GetControllerInputReleasedTime(SH_CONTROLLERCODE code,
size_t controllerNum = 0) noexcept
{
if (controllerNum >= XUSER_MAX_COUNT) return 0.0;
return controllersReleasedTime[controllerNum][static_cast<size_t>(code)];
}
/*------------------------------------------------------------------------*/
/* Binding Functions */
/*------------------------------------------------------------------------*/
//Add a new binding to the map
static inline void BindingsAdd(std::string newBindingName) noexcept
{
bindings.insert({ newBindingName, SHLogicalBindingData() });
}
//Remove a binding from the map
//Returns 1 if found and removed, 0 if not found
static inline size_t BindingsRemove(std::string targetBindingName) noexcept
{
return bindings.erase(targetBindingName);
}
//Clears all bindings from the list
static inline void BindingsClear() noexcept
{
bindings.clear();
}
//Get the number of bindings present
static inline size_t BindingsCount() noexcept
{
return bindings.size();
}
//Check positive keycodes to binding
static inline std::set<SH_KEYCODE> const& BindingsGetPositiveKeyCodes(std::string bindingName) noexcept
{
return bindings[bindingName].positiveKeyCodes;
}
//Add positive SH_KEYCODE to binding
static inline void BindingsAddPositiveKeyCode(std::string targetBindingName,
SH_KEYCODE toAdd) noexcept
{
bindings[targetBindingName].positiveKeyCodes.insert(toAdd);
}
//Remove positive SH_KEYCODE from binding
//If toRemove found and removed, returns 1. Otherwise, 0.
static inline size_t BindingsRemovePositiveKeyCode(std::string targetBindingName,
SH_KEYCODE toRemove) noexcept
{
return bindings[targetBindingName].positiveKeyCodes.erase(toRemove);
}
//Check negative keycodes to binding
static inline std::set<SH_KEYCODE> const& BindingsGetNegativeKeyCodes(std::string bindingName) noexcept
{
return bindings[bindingName].negativeKeyCodes;
}
//Add negative SH_KEYCODE to binding
static inline void BindingsAddNegativeKeyCode(std::string targetBindingName,
SH_KEYCODE toAdd) noexcept
{
bindings[targetBindingName].negativeKeyCodes.insert(toAdd);
}
//Remove negative SH_KEYCODE from binding
//If toRemove found and removed, returns 1. Otherwise, 0.
static inline size_t BindingsRemoveNegativeKeyCode(std::string targetBindingName,
SH_KEYCODE toRemove) noexcept
{
return bindings[targetBindingName].negativeKeyCodes.erase(toRemove);
}
//Check positive controllercodes to binding
static inline std::set<SH_CONTROLLERCODE> const& BindingsGetPositiveControllerCodes(std::string bindingName) noexcept
{
return bindings[bindingName].positiveControllerCodes;
}
//Add positive SH_CONTROLLERCODE to binding
static inline void BindingsAddPositiveControllerCode(std::string targetBindingName,
SH_CONTROLLERCODE toAdd) noexcept
{
bindings[targetBindingName].positiveControllerCodes.insert(toAdd);
}
//Remove positive SH_CONTROLLERCODE from binding
//If toRemove found and removed, returns 1. Otherwise, 0.
static inline size_t BindingsRemovePositiveControllerCode(std::string targetBindingName,
SH_CONTROLLERCODE toRemove) noexcept
{
return bindings[targetBindingName].positiveControllerCodes.erase(toRemove);
}
//Check negative controllercodes to binding
static inline std::set<SH_CONTROLLERCODE> const& BindingsGetNegativeControllerCodes(std::string bindingName) noexcept
{
return bindings[bindingName].negativeControllerCodes;
}
//Add negative SH_CONTROLLERCODE to binding
static inline void BindingsAddNegativeControllerCode(std::string targetBindingName,
SH_CONTROLLERCODE toAdd) noexcept
{
bindings[targetBindingName].negativeControllerCodes.insert(toAdd);
}
//Remove negative SH_CONTROLLERCODE from binding
//If toRemove found and removed, returns 1. Otherwise, 0.
static inline size_t BindingsRemoveNegativeControllerCode(std::string targetBindingName,
SH_CONTROLLERCODE toRemove) noexcept
{
return bindings[targetBindingName].negativeControllerCodes.erase(toRemove);
}
//Mouse movement bindings
static inline double const BindingsGetMouseXPositiveMultiplier(std::string bindingName) noexcept
{
return bindings[bindingName].mouseXPositiveMultiplier;
}
static inline void BindingsSetMouseXPositiveMultiplier(std::string bindingName, double newValue) noexcept
{
bindings[bindingName].mouseXPositiveMultiplier = newValue;
}
static inline double const BindingsGetMouseYPositiveMultiplier(std::string bindingName) noexcept
{
return bindings[bindingName].mouseXPositiveMultiplier;
}
static inline void BindingsSetMouseYPositiveMultiplier(std::string bindingName, double newValue) noexcept
{
bindings[bindingName].mouseXPositiveMultiplier = newValue;
}
//Get the axis value of binding, between -1 and 1
static double GetBindingAxis(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Whether binding is being held or not
//Does not work for mouse movement
static bool GetBindingPositiveButton(std::string bindingName, size_t controllerNumber = 0) noexcept;
static bool GetBindingNegativeButton(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Whether binding is pressed down IN THIS FRAME ONLY
//Does not work for mouse movement
static bool GetBindingPositiveButtonDown(std::string bindingName, size_t controllerNumber = 0) noexcept;
static bool GetBindingNegativeButtonDown(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Whether binding is released IN THIS FRAME ONLY
//Does not work for mouse movement
static bool GetBindingPositiveButtonUp(std::string bindingName, size_t controllerNumber = 0) noexcept;
static bool GetBindingNegativeButtonUp(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Binding times
//Does not work for mouse movement
static double GetBindingPositiveHeldTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
static double GetBindingNegativeHeldTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Does not work for mouse movement
static double GetBindingPositiveReleasedTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
static double GetBindingNegativeReleasedTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
//Binding mouse velocity
//Only for mouse movement
static double GetBindingMouseVelocity(std::string bindingName, size_t controllerNumber = 0) noexcept;
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/* Other Functions */ /* Other Functions */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@ -482,10 +810,36 @@ namespace SHADE
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static constexpr size_t MAX_KEYS = UCHAR_MAX + 1; static constexpr size_t MAX_KEYS = UCHAR_MAX + 1;
//How many recognised controller inputs there are
//To see the list, see the enum class in this file
static constexpr size_t MAX_CONTROLLER_INPUT = 20;
//On/off button count
static constexpr size_t NUM_CONTROLLER_BUTTON = 14;
//8-bit trigger values
static constexpr size_t NUM_CONTROLLER_TRIGGER = 2;
//16-bit thumbstick values
static constexpr size_t NUM_CONTROLLER_THUMBSTICK = 4;
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
//If the last input is from controller(s) or KB/M
//True if from controller(s), False if from KB/M
//Useful for switching control hints between controllers and KB/M
static bool controllerInUse;
//BINDINGS//////////////////////////////////////////////////////////////////
//Key is for binding names, they must be unique
//Multiple physical inputs per virtual/logical input are to be added to
//sets inside the logicalBinding values
//TODO make this an array of 4 / 5 users for multiplayer support
static std::map<std::string, SHLogicalBindingData> bindings;
//KEYBOARD AND MOUSE BUTTONS//////////////////////////////////////////////// //KEYBOARD AND MOUSE BUTTONS////////////////////////////////////////////////
//How many keys are presently being pressed //How many keys are presently being pressed
@ -558,15 +912,48 @@ namespace SHADE
//CONTROLLER VARIABLES////////////////////////////////////////////////////// //CONTROLLER VARIABLES//////////////////////////////////////////////////////
//OTHER VARIABLES/////////////////////////////////////////////////////////// //Count how many controllers are presently connected
//Useful for if the game is to decide to take in controller or KB/M input
//Between 0 and 4 (inclusive)
static unsigned char controllersConnectedCount;
//Axis bindings //How many inputs (of any kind) on the controller are being used now
//X //Includes analog triggers and thumbsticks
static unsigned controllersInputCount[XUSER_MAX_COUNT];
//Y //How many DIGITAL buttons on the controller are being pressed now
static unsigned controllersButtonCount[XUSER_MAX_COUNT];
//Other mappings //Current state of controllers
//First index is for controller number
//Second index is for input type
static short controllers[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//Buffer //State of controllers in the last frame
//First index is for controller number
//Second index is for input type
static short controllersLast[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//Held and released times
//Controller held durations
//Stops ticking up when released
//Will be reset when held again
static double controllersHeldTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
//Key released durations
//Stops ticking up when held
//Will be reset when off again
static double controllersReleasedTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
/*------------------------------------------------------------------------*/
/* Internal Helper Functions */
/*------------------------------------------------------------------------*/
//Internal helper function for checking if input is considered held or not
static bool controllerConsideredHeld(size_t inputIdx, short value) noexcept;
//Internal helper function for getting normalised controller value
static double controllerNormalisedValue(size_t inputIdx, short value) noexcept;
}; };
} }

View File

@ -0,0 +1,167 @@
//#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
#define MASK_WIDTH 3
#define HALF_M_WIDTH MASK_WIDTH / 2
#define SHM_WIDTH 18
#define NUM_MASKS 8
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 resultImage;
const float kirsch[8][3][3] = {
{
{5, 5, 5},
{-3, 0, -3}, /*rotation 1 */
{-3, -3, -3}
},
{
{5, 5, -3},
{5, 0, -3}, /*rotation 2 */
{-3, -3, -3}
},
{
{5, -3, -3},
{5, 0, -3}, /*rotation 3 */
{5, -3, -3}
},
{
{-3, -3, -3},
{5, 0, -3}, /*rotation 4 */
{5, 5, -3}
},
{
{-3, -3, -3},
{-3, 0, -3}, /*rotation 5 */
{5, 5, 5}
},
{
{-3, -3, -3},
{-3, 0, 5}, /*rotation 6 */
{-3, 5, 5}
},
{
{-3, -3, 5},
{-3, 0, 5}, /*rotation 7 */
{-3, -3, 5}
},
{
{-3, 5, 5},
{-3, 0, 5}, /*rotation 8 */
{-3, -3, -3}
}
};
vec3 GetImageValues(ivec2 uv, ivec2 inputImageSize)
{
if (uv.x >= 0 && uv.y >= 0 && uv.x < inputImageSize.x && uv.y < inputImageSize.y)
{
return imageLoad(inputImage, uv).rgb;
}
else
return vec3(0.0f);
}
//two extra row/col
shared vec3 sData[16 + 2][16 + 2];
void main()
{
// convenient variables
ivec3 globalThread = ivec3(gl_GlobalInvocationID);
ivec3 localThread = ivec3(gl_LocalInvocationID);
ivec2 inputImageSize = imageSize(inputImage);
// load shared memory
ivec2 start = ivec2(gl_WorkGroupID) * ivec2(gl_WorkGroupSize) - ivec2(HALF_M_WIDTH);
for (int i = localThread.x; i < SHM_WIDTH; i += int(gl_WorkGroupSize.x))
{
for (int j = localThread.y; j < SHM_WIDTH; j += int(gl_WorkGroupSize.y))
{
// get from source image (either real values or 0)
vec3 sourceValue = GetImageValues(start + ivec2(i, j), inputImageSize);
sData[i][j] = sourceValue;
}
}
// wait for shared memory to finish loading
barrier();
// max (between all 8 masks)
vec3 maxSum = vec3(0.0f);
// loop through all masks
for (int i = 0; i < NUM_MASKS; ++i)
{
vec3 sum = vec3(0.0f);
// start of shared memory
ivec2 shmStart = ivec2(localThread + HALF_M_WIDTH);
for (int j = -1; j < HALF_M_WIDTH + 1; ++j)
{
for (int k = -1; k < HALF_M_WIDTH + 1; ++k)
{
// Perform convolution using shared_memory
sum += sData[shmStart.x + j][shmStart.y + k] * kirsch[i][j + 1][k + 1];
}
}
// Get highest sum
maxSum = max(sum, maxSum);
}
// average the max sum
maxSum = min(max(maxSum / 8, 0), 1.0f);
// store result into result image
imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(maxSum, 1.0f));
}

Binary file not shown.