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

This commit is contained in:
Xiao Qi 2022-09-26 14:40:57 +08:00
commit 1c45b49937
24 changed files with 1228 additions and 158 deletions

View File

@ -23,6 +23,7 @@
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Math/Transform/SHTransformSystem.h" #include "Math/Transform/SHTransformSystem.h"
#include "Input/SHInputManagerSystem.h"
#include "Scenes/SBTestScene.h" #include "Scenes/SBTestScene.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
@ -54,6 +55,7 @@ namespace Sandbox
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
SHADE::SHSystemManager::CreateSystem<SHADE::SHInputManagerSystem>();
// Create Routines // Create Routines
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>();
@ -74,6 +76,8 @@ namespace Sandbox
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>(); SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>(); SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHInputManagerSystem, SHADE::SHInputManagerSystem::InputManagerRoutine>();
//TODO: REMOVE AFTER PRESENTATION //TODO: REMOVE AFTER PRESENTATION
SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.fbx"); SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.fbx");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds"); SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");

View File

@ -55,12 +55,12 @@ namespace Sandbox
graphicsSystem->BuildMeshBuffers(); graphicsSystem->BuildMeshBuffers();
// Create Materials // Create Materials
auto matInst = graphicsSystem->AddMaterialInstance(); auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
// Create Stress Test Objects // Create Stress Test Objects
static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f }; static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f };
constexpr int NUM_ROWS = 200; constexpr int NUM_ROWS = 1;
constexpr int NUM_COLS = 100; constexpr int NUM_COLS = 1;
static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f }; static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f };
static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f }; static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f };
//for (int z = 0; z < NUM_ROWS; ++z) //for (int z = 0; z < NUM_ROWS; ++z)

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="SHADE::Handle&lt;*&gt;">
<DisplayString Condition="library==nullptr">NULL</DisplayString>
<DisplayString>ID = {id.Data.Index} Version = {id.Data.Version} Type = {"$T1"} </DisplayString>
<Expand>
<ExpandedItem>(*library).objects.denseArray[(*library).objects.sparseArray[id.Data.Index]]</ExpandedItem>
</Expand>
</Type>
</AutoVisualizer>

View File

@ -15,7 +15,8 @@ project "SHADE_Engine"
"%{prj.location}/src/**.hpp", "%{prj.location}/src/**.hpp",
"%{prj.location}/src/**.c", "%{prj.location}/src/**.c",
"%{prj.location}/src/**.cpp", "%{prj.location}/src/**.cpp",
"%{prj.location}/src/**.glsl" "%{prj.location}/src/**.glsl",
"%{prj.location}/**.natvis"
} }
includedirs includedirs

View File

@ -16,7 +16,7 @@ namespace SHADE
{ {
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Frees the command buffer. Frees the command buffer.
@ -30,13 +30,13 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Only the command buffer is allocated using Only the command buffer is allocated using
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit, is resetting VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit, is resetting
individually permitted. Otherwise, throw exception. IMPORTANT NOTE: individually permitted. Otherwise, throw exception. IMPORTANT NOTE:
the command buffer cannot be in the pending state!!! the command buffer cannot be in the pending state!!!
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::Reset(void) void SHVkCommandBuffer::Reset(void)
@ -67,10 +67,10 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Begins the command buffer. Begins the command buffer.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::BeginRecording(void) noexcept void SHVkCommandBuffer::BeginRecording(void) noexcept
@ -108,10 +108,10 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
End the recording of a command buffer. End the recording of a command buffer.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::EndRecording(void) noexcept void SHVkCommandBuffer::EndRecording(void) noexcept
@ -121,21 +121,21 @@ namespace SHADE
SHLOG_ERROR("Command Buffer not in recording state, cannot end recording. "); SHLOG_ERROR("Command Buffer not in recording state, cannot end recording. ");
return; return;
} }
vkCommandBuffer.end(); vkCommandBuffer.end();
cmdBufferState = SH_CMD_BUFFER_STATE::EXECUTABLE; cmdBufferState = SH_CMD_BUFFER_STATE::EXECUTABLE;
} }
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Begins a renderpass in the command buffer. 2 important things to note Begins a renderpass in the command buffer. 2 important things to note
here, the command buffer used MUST be a primary command buffer and here, the command buffer used MUST be a primary command buffer and
command buffer MUST be in a recording state. command buffer MUST be in a recording state.
\param renderpassHdl \param renderpassHdl
Renderpass for obvious reasons. Renderpass for obvious reasons.
\param framebufferHdl \param framebufferHdl
Framebuffer required in the begin info. Framebuffer required in the begin info.
@ -145,7 +145,7 @@ namespace SHADE
\param extent \param extent
Extent of the render area in the framebuffer. Extent of the render area in the framebuffer.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::BeginRenderpass(Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkFramebuffer> const& framebufferHdl, vk::Offset2D offset, vk::Extent2D extent) noexcept void SHVkCommandBuffer::BeginRenderpass(Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkFramebuffer> const& framebufferHdl, vk::Offset2D offset, vk::Extent2D extent) noexcept
@ -170,7 +170,7 @@ namespace SHADE
vk::RenderPassBeginInfo renderPassInfo{}; vk::RenderPassBeginInfo renderPassInfo{};
renderPassInfo.renderPass = renderpassHdl->GetVkRenderpass(); renderPassInfo.renderPass = renderpassHdl->GetVkRenderpass();
renderPassInfo.framebuffer = framebufferHdl->GetVkFramebuffer(); renderPassInfo.framebuffer = framebufferHdl->GetVkFramebuffer();
// If the extent passed in is 0, use the framebuffer dimensions instead. // If the extent passed in is 0, use the framebuffer dimensions instead.
if (extent.width == 0 && extent.height == 0) if (extent.width == 0 && extent.height == 0)
renderPassInfo.renderArea.extent = framebufferExtent; renderPassInfo.renderArea.extent = framebufferExtent;
@ -192,16 +192,16 @@ namespace SHADE
} }
// Begin the render pass // Begin the render pass
vkCommandBuffer.beginRenderPass (&renderPassInfo, vk::SubpassContents::eInline); vkCommandBuffer.beginRenderPass(&renderPassInfo, vk::SubpassContents::eInline);
} }
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Ends a renderpass. Ends a renderpass.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::EndRenderpass(void) noexcept void SHVkCommandBuffer::EndRenderpass(void) noexcept
@ -216,14 +216,14 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Sets the viewport dynamically for the command buffer. #NoteToSelf: Sets the viewport dynamically for the command buffer. #NoteToSelf:
Dynamic state will not affect pipelines that don't use dynamic state Dynamic state will not affect pipelines that don't use dynamic state
so there isn't a need to do any checks. Also, setting dynamic state like so there isn't a need to do any checks. Also, setting dynamic state like
this only needs to happen ONCE per command buffer UNLESS a different this only needs to happen ONCE per command buffer UNLESS a different
viewport is to be used for different drawing commands. viewport is to be used for different drawing commands.
\param vpWidth \param vpWidth
viewport width viewport width
@ -254,7 +254,7 @@ namespace SHADE
\param vpMaxDepth \param vpMaxDepth
viewport maximum depth value viewport maximum depth value
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::SetViewportScissor(float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX /*= 0.0f*/, float vpY /*= 0.0f*/, int32_t sX /*= 0.0f*/, int32_t sY /*= 0.0f*/, float vpMinDepth /*= 0.0f*/, float vpMaxDepth /*= 1.0f*/) noexcept void SHVkCommandBuffer::SetViewportScissor(float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX /*= 0.0f*/, float vpY /*= 0.0f*/, int32_t sX /*= 0.0f*/, int32_t sY /*= 0.0f*/, float vpMinDepth /*= 0.0f*/, float vpMaxDepth /*= 1.0f*/) noexcept
@ -283,13 +283,13 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Binds a pipeline object to the command buffer. Binds a pipeline object to the command buffer.
\param pipelineHdl \param pipelineHdl
The pipeline to bind. The pipeline to bind.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::BindPipeline(Handle<SHVkPipeline> const& pipelineHdl) noexcept void SHVkCommandBuffer::BindPipeline(Handle<SHVkPipeline> const& pipelineHdl) noexcept
@ -307,7 +307,7 @@ namespace SHADE
/*! /*!
\brief \brief
Binds a buffer to the vertex buffer binding point specified in Binds a buffer to the vertex buffer binding point specified in
bindingPoint. bindingPoint.
\param bindingPoint \param bindingPoint
@ -321,29 +321,32 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept void SHVkCommandBuffer::BindVertexBuffer(uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept
{ {
if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING)
{ {
auto bufferHandle = buffer->GetVkBuffer(); if (buffer)
vkCommandBuffer.bindVertexBuffers (bindingPoint, 1, &bufferHandle, &offset); {
auto bufferHandle = buffer->GetVkBuffer();
vkCommandBuffer.bindVertexBuffers(bindingPoint, 1, &bufferHandle, &offset);
}
} }
} }
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Binds an index buffer to the pipeline. Binds an index buffer to the pipeline.
\param buffer \param buffer
The buffer to bind. The buffer to bind.
\param startingIndex \param startingIndex
The starting index in the index buffer. For example, 0 would mean The starting index in the index buffer. For example, 0 would mean
starting at the beginning. 5 would mean starting at byte offset starting at the beginning. 5 would mean starting at byte offset
size(uint32_t) * 5. size(uint32_t) * 5.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::BindIndexBuffer(Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept void SHVkCommandBuffer::BindIndexBuffer(Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept
@ -351,33 +354,33 @@ namespace SHADE
if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING)
{ {
auto bufferHandle = buffer->GetVkBuffer(); auto bufferHandle = buffer->GetVkBuffer();
vkCommandBuffer.bindIndexBuffer (bufferHandle, sizeof (uint32_t) * startingIndex, vk::IndexType::eUint32); vkCommandBuffer.bindIndexBuffer(bufferHandle, sizeof(uint32_t) * startingIndex, vk::IndexType::eUint32);
} }
} }
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets) void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
{ {
vkCommandBuffer.bindDescriptorSets (bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
} }
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Calls vkCmdDraw. Calls vkCmdDraw.
\param vertexCount \param vertexCount
How many vertices to draw How many vertices to draw
\param instanceCount \param instanceCount
Number of instances to draw Number of instances to draw
\param firstVertex \param firstVertex
First vertex in the buffer of vertices to start from First vertex in the buffer of vertices to start from
\param firstInstance \param firstInstance
First instance to start from. First instance to start from.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept void SHVkCommandBuffer::DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept
@ -387,30 +390,30 @@ 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;
} }
vkCommandBuffer.draw (vertexCount, instanceCount, firstVertex, firstInstance); vkCommandBuffer.draw(vertexCount, instanceCount, firstVertex, firstInstance);
} }
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Issues a non-instanced indexed draw call. Issues a non-instanced indexed draw call.
\param indexCount \param indexCount
Number of indices to draw. Number of indices to draw.
\param firstIndex \param firstIndex
Starting index. if the array was 0, 2, 5, 4, and we indicated this to be Starting index. if the array was 0, 2, 5, 4, and we indicated this to be
1. The draw call would start from index 2. 1. The draw call would start from index 2.
\param vertexOffset \param vertexOffset
Starting vertex offset. This would indicate that vertex pulling should Starting vertex offset. This would indicate that vertex pulling should
start from a certain vertex. So a vertex offset of 3 (for example) would start from a certain vertex. So a vertex offset of 3 (for example) would
mean an index of 0 would mean the 3rd vertex. mean an index of 0 would mean the 3rd vertex.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept void SHVkCommandBuffer::DrawIndexed(uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept
{ {
if (cmdBufferState != SH_CMD_BUFFER_STATE::RECORDING) if (cmdBufferState != SH_CMD_BUFFER_STATE::RECORDING)
{ {
@ -422,7 +425,7 @@ namespace SHADE
vkCommandBuffer.drawIndexed(indexCount, 1, firstIndex, vertexOffset, 0); vkCommandBuffer.drawIndexed(indexCount, 1, firstIndex, vertexOffset, 0);
} }
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -445,35 +448,36 @@ namespace SHADE
return; return;
} }
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand)); if (indirectDrawData)
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
} }
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
( (
src, dst, vk::ImageLayout::eTransferDstOptimal, src, dst, vk::ImageLayout::eTransferDstOptimal,
static_cast<uint32_t>(copyInfo.size()), copyInfo.data() static_cast<uint32_t>(copyInfo.size()), copyInfo.data()
); );
} }
void SHVkCommandBuffer::PipelineBarrier( void SHVkCommandBuffer::PipelineBarrier(
vk::PipelineStageFlags srcStage, vk::PipelineStageFlags srcStage,
vk::PipelineStageFlags dstStage, vk::PipelineStageFlags dstStage,
vk::DependencyFlags deps, vk::DependencyFlags deps,
std::vector<vk::MemoryBarrier> const& memoryBarriers, std::vector<vk::MemoryBarrier> const& memoryBarriers,
std::vector<vk::BufferMemoryBarrier> const& bufferMemoryBarriers, std::vector<vk::BufferMemoryBarrier> const& bufferMemoryBarriers,
std::vector<vk::ImageMemoryBarrier> const& imageMemoryBarriers std::vector<vk::ImageMemoryBarrier> const& imageMemoryBarriers
) const noexcept ) const noexcept
{ {
vkCommandBuffer.pipelineBarrier ( vkCommandBuffer.pipelineBarrier(
srcStage, srcStage,
dstStage, dstStage,
deps, deps,
memoryBarriers, memoryBarriers,
bufferMemoryBarriers, bufferMemoryBarriers,
imageMemoryBarriers imageMemoryBarriers
); );
} }
bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept
@ -498,10 +502,10 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Calls vkCmdPushConstants and submits data stored in command buffer. Calls vkCmdPushConstants and submits data stored in command buffer.
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept
@ -514,13 +518,13 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Simply returns the command buffer handle. Simply returns the command buffer handle.
\return \return
The command buffer handle. The command buffer handle.
*/ */
/***************************************************************************/ /***************************************************************************/
vk::CommandBuffer const& SHVkCommandBuffer::GetVkCommandBuffer(void) const noexcept vk::CommandBuffer const& SHVkCommandBuffer::GetVkCommandBuffer(void) const noexcept
@ -530,11 +534,11 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
See https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetRenderAreaGranularity.html See https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetRenderAreaGranularity.html
or look up vkGetRenderAreaGranularity. or look up vkGetRenderAreaGranularity.
\param renderpassHdl \param renderpassHdl
Renderpass to get info from. Renderpass to get info from.
@ -544,9 +548,9 @@ namespace SHADE
\param renderArea \param renderArea
For the comparison. Again, look it up on the webpage. For the comparison. Again, look it up on the webpage.
\return \return
If optimal, true. otherwise false. If optimal, true. otherwise false.
*/ */
/***************************************************************************/ /***************************************************************************/
bool SHVkCommandBuffer::IsRenderAreaOptimal(Handle<SHVkRenderpass> const& renderpassHdl, vk::Extent2D const& framebufferExtent, vk::Rect2D const& renderArea) const noexcept bool SHVkCommandBuffer::IsRenderAreaOptimal(Handle<SHVkRenderpass> const& renderpassHdl, vk::Extent2D const& framebufferExtent, vk::Rect2D const& renderArea) const noexcept
@ -558,14 +562,14 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Setter for the state of the command buffer. Setter for the state of the command buffer.
\param state \param state
\return \return
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::SetState(SH_CMD_BUFFER_STATE state) noexcept void SHVkCommandBuffer::SetState(SH_CMD_BUFFER_STATE state) noexcept
@ -575,12 +579,12 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Returns the state of the command buffer. Returns the state of the command buffer.
\return \return
*/ */
/***************************************************************************/ /***************************************************************************/
SH_CMD_BUFFER_STATE SHVkCommandBuffer::GetState(void) const noexcept SH_CMD_BUFFER_STATE SHVkCommandBuffer::GetState(void) const noexcept
@ -590,14 +594,14 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Creates a command buffer. Cmd buffer can be primary or secondary. If Creates a command buffer. Cmd buffer can be primary or secondary. If
secondary, flags will automatically have renderpass continue bit. Command secondary, flags will automatically have renderpass continue bit. Command
pool used to create this command buffer will determine whether or not pool used to create this command buffer will determine whether or not
this buffer will be allocated with this buffer will be allocated with
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT using the reset mode. VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT using the reset mode.
\param logicalDevice \param logicalDevice
Need a logical device to create a buffer. Need a logical device to create a buffer.
@ -606,7 +610,7 @@ namespace SHADE
\param type \param type
Type of the command buffer; primary or secondary. Type of the command buffer; primary or secondary.
*/ */
/***************************************************************************/ /***************************************************************************/
SHVkCommandBuffer::SHVkCommandBuffer(Handle<SHVkCommandPool> const& commandPool, SH_CMD_BUFFER_TYPE type) noexcept SHVkCommandBuffer::SHVkCommandBuffer(Handle<SHVkCommandPool> const& commandPool, SH_CMD_BUFFER_TYPE type) noexcept
@ -616,7 +620,7 @@ namespace SHADE
, parentPoolResetMode{ SH_CMD_POOL_RESET::POOL_BASED } , parentPoolResetMode{ SH_CMD_POOL_RESET::POOL_BASED }
, usageFlags{} , usageFlags{}
, commandBufferCount{ 0 } , commandBufferCount{ 0 }
, parentPool{commandPool} , parentPool{ commandPool }
, pushConstantData{} , pushConstantData{}
{ {
@ -657,54 +661,54 @@ namespace SHADE
commandBufferType = type; commandBufferType = type;
commandBufferCount = allocateInfo.commandBufferCount; commandBufferCount = allocateInfo.commandBufferCount;
if (parentPool->GetIsTransient ()) if (parentPool->GetIsTransient())
usageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; usageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
if (commandBufferType == SH_CMD_BUFFER_TYPE::SECONDARY) if (commandBufferType == SH_CMD_BUFFER_TYPE::SECONDARY)
usageFlags |= vk::CommandBufferUsageFlagBits::eRenderPassContinue; usageFlags |= vk::CommandBufferUsageFlagBits::eRenderPassContinue;
// Reset all the push constant data to 0 // Reset all the push constant data to 0
memset (pushConstantData, 0, PUSH_CONSTANT_SIZE); memset(pushConstantData, 0, PUSH_CONSTANT_SIZE);
} }
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Move ctor. Invalidates Vulkan handles. Move ctor. Invalidates Vulkan handles.
\param rhs \param rhs
the other command buffer. the other command buffer.
*/ */
/***************************************************************************/ /***************************************************************************/
SHVkCommandBuffer::SHVkCommandBuffer(SHVkCommandBuffer&& rhs) noexcept SHVkCommandBuffer::SHVkCommandBuffer(SHVkCommandBuffer&& rhs) noexcept
: vkCommandBuffer {std::move (rhs.vkCommandBuffer)} : vkCommandBuffer{ std::move(rhs.vkCommandBuffer) }
, cmdBufferState {rhs.cmdBufferState} , cmdBufferState{ rhs.cmdBufferState }
, commandBufferType {rhs.commandBufferType} , commandBufferType{ rhs.commandBufferType }
, parentPoolResetMode {rhs.parentPoolResetMode} , parentPoolResetMode{ rhs.parentPoolResetMode }
, usageFlags {rhs.usageFlags} , usageFlags{ rhs.usageFlags }
, commandBufferCount {rhs.commandBufferCount} , commandBufferCount{ rhs.commandBufferCount }
, parentPool {rhs.parentPool} , parentPool{ rhs.parentPool }
, boundPipelineLayoutHdl{rhs.boundPipelineLayoutHdl } , boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl }
{ {
memcpy (pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
rhs.vkCommandBuffer = VK_NULL_HANDLE; rhs.vkCommandBuffer = VK_NULL_HANDLE;
} }
/***************************************************************************/ /***************************************************************************/
/*! /*!
\brief \brief
Move assignment operator. Invalidates Vulkan handles. Move assignment operator. Invalidates Vulkan handles.
\param rhs \param rhs
The other Vulkan Handle. The other Vulkan Handle.
\return \return
a reference itself. a reference itself.
*/ */
/***************************************************************************/ /***************************************************************************/
SHVkCommandBuffer& SHVkCommandBuffer::operator=(SHVkCommandBuffer&& rhs) noexcept SHVkCommandBuffer& SHVkCommandBuffer::operator=(SHVkCommandBuffer&& rhs) noexcept

View File

@ -39,7 +39,8 @@ namespace SHADE
std::vector<vk::DescriptorPoolSize> Limits = std::vector<vk::DescriptorPoolSize> Limits =
{ {
{ vk::DescriptorType::eCombinedImageSampler, 100 }, { vk::DescriptorType::eCombinedImageSampler, 100 },
{ vk::DescriptorType::eUniformBuffer, 100 } { vk::DescriptorType::eUniformBuffer, 100 },
{ vk::DescriptorType::eUniformBufferDynamic, 100 }
}; };
/// <summary> /// <summary>
/// Maximum number of descriptor sets allowed /// Maximum number of descriptor sets allowed

View File

@ -58,6 +58,9 @@ namespace SHADE
// Add renderable in // Add renderable in
subBatch->Renderables.insert(renderable); subBatch->Renderables.insert(renderable);
// Also add material instance in
referencedMatInstances.insert(renderable->GetMaterial());
// Mark all as dirty // Mark all as dirty
setAllDirtyFlags(); setAllDirtyFlags();
} }
@ -67,8 +70,8 @@ namespace SHADE
// Check if we have a SubBatch with the same mesh yet // Check if we have a SubBatch with the same mesh yet
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch) auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
{ {
return batch.Mesh == renderable->Mesh; return batch.Mesh == renderable->Mesh;
}); });
// Attempt to remove if it exists // Attempt to remove if it exists
if (subBatch == subBatches.end()) if (subBatch == subBatches.end())
@ -76,6 +79,22 @@ namespace SHADE
subBatch->Renderables.erase(renderable); subBatch->Renderables.erase(renderable);
// Check if other renderables in subBatches contain the same material instance
bool matUnused = true;
for (const auto& sb : subBatches)
for (const auto& rend : sb.Renderables)
{
if (rend->GetMaterial() == renderable->GetMaterial())
{
matUnused = false;
break;
}
}
// Material is no longer in this library, so we remove it
if (matUnused)
referencedMatInstances.erase(renderable->GetMaterial());
// Mark all as dirty // Mark all as dirty
for (bool& dirt : isDirty) for (bool& dirt : isDirty)
dirt = true; dirt = true;
@ -101,7 +120,61 @@ namespace SHADE
} }
} }
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex) void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex)
{
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
return;
}
// Check if there are even material properties to update
if (!matPropsData)
return;
// Check if any materials have changed
bool hasChanged = false;
for (const auto& material : referencedMatInstances)
{
if (material->HasChanged())
{
hasChanged = true;
break;
}
}
// We need to update all the material buffers if the materials have changed
if (hasChanged)
{
for (auto& dirt : matBufferDirty)
dirt = true;
}
// Check if this frame's buffer is dirty
if (!matBufferDirty[frameIndex])
return;
// Build CPI Buffer
char* propsCurrPtr = matPropsData.get();
for (auto& subBatch : subBatches)
for (const SHRenderable* renderable : subBatch.Renderables)
{
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
propsCurrPtr += singleMatPropSize;
}
// Transfer to GPU
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
vk::BufferUsageFlagBits::eStorageBuffer
);
// This frame is updated
matBufferDirty[frameIndex] = false;
}
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
{ {
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{ {
@ -130,10 +203,11 @@ namespace SHADE
} }
// Transfer to GPU // Transfer to GPU
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), transformData.size() * sizeof(SHMatrix), 0, 0); if (transformDataBuffer[frameIndex])
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
} }
void SHBatch::Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) void SHBatch::Build(Handle<SHVkLogicalDevice> _device, uint32_t frameIndex)
{ {
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{ {
@ -169,7 +243,6 @@ namespace SHADE
vk::ShaderStageFlagBits::eFragment vk::ShaderStageFlagBits::eFragment
); );
const bool EMPTY_MAT_PROPS = !SHADER_INFO; const bool EMPTY_MAT_PROPS = !SHADER_INFO;
Byte singleMatPropSize = 0;
Byte matPropTotalBytes = 0; Byte matPropTotalBytes = 0;
if (!EMPTY_MAT_PROPS) if (!EMPTY_MAT_PROPS)
{ {
@ -231,14 +304,14 @@ namespace SHADE
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand)); const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES, _device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
BuffUsage::eIndirectBuffer BuffUsage::eIndirectBuffer
); );
// - Transform Buffer // - Transform Buffer
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)); const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, _device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer
); );
// - Material Properties Buffer // - Material Properties Buffer
@ -246,12 +319,15 @@ namespace SHADE
{ {
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize), _device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
BuffUsage::eStorageBuffer BuffUsage::eStorageBuffer
); );
} }
isDirty[frameIndex] = false; isDirty[frameIndex] = false;
// Save logical device
this->device = _device;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -34,6 +34,7 @@ namespace SHADE
class SHMesh; class SHMesh;
class SHRenderable; class SHRenderable;
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHMaterialInstance;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -73,6 +74,7 @@ namespace SHADE
void Add(const SHRenderable* renderable); void Add(const SHRenderable* renderable);
void Remove(const SHRenderable* renderable); void Remove(const SHRenderable* renderable);
void Clear(); void Clear();
void UpdateMaterialBuffer(uint32_t frameIndex);
void UpdateTransformBuffer(uint32_t frameIndex); void UpdateTransformBuffer(uint32_t frameIndex);
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex); void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex); void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
@ -86,8 +88,12 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
// Resources
Handle<SHVkLogicalDevice> device;
// Batch Properties // Batch Properties
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> matBufferDirty;
// Batch Tree // Batch Tree
std::vector<SHSubBatch> subBatches; std::vector<SHSubBatch> subBatches;
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty; std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty;
@ -96,6 +102,7 @@ namespace SHADE
std::vector<SHMatrix> transformData; std::vector<SHMatrix> transformData;
std::unique_ptr<char> matPropsData; std::unique_ptr<char> matPropsData;
Byte matPropsDataSize = 0; Byte matPropsDataSize = 0;
Byte singleMatPropSize = 0;
bool isCPUBuffersDirty = true; bool isCPUBuffersDirty = true;
// GPU Buffers // GPU Buffers
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer; std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer;

View File

@ -109,11 +109,11 @@ namespace SHADE
superBatches.clear(); superBatches.clear();
} }
void SHBatcher::UpdateTransformBuffer(uint32_t frameIndex) void SHBatcher::UpdateBuffers(uint32_t frameIndex)
{ {
for (auto& batch : superBatches) for (auto& batch : superBatches)
{ {
batch->UpdateTransformBuffer(frameIndex); batch->UpdateBuffers(frameIndex);
} }
} }

View File

@ -53,7 +53,7 @@ namespace SHADE
void RemoveFromBatch(SHRenderable const* renderable); void RemoveFromBatch(SHRenderable const* renderable);
void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex); void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
void ClearBatches(); void ClearBatches();
void UpdateTransformBuffer(uint32_t frameIndex); void UpdateBuffers(uint32_t frameIndex);
void RegisterSuperBatch(Handle<SHSuperBatch> superBatch); void RegisterSuperBatch(Handle<SHSuperBatch> superBatch);
void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch); void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch);

View File

@ -78,10 +78,11 @@ namespace SHADE
batches.clear(); batches.clear();
} }
void SHSuperBatch::UpdateTransformBuffer(uint32_t frameIndex) void SHSuperBatch::UpdateBuffers(uint32_t frameIndex)
{ {
for (auto& batch : batches) for (auto& batch : batches)
{ {
batch.UpdateMaterialBuffer(frameIndex);
batch.UpdateTransformBuffer(frameIndex); batch.UpdateTransformBuffer(frameIndex);
} }
} }

View File

@ -54,8 +54,8 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void Add(const SHRenderable* renderable) noexcept; void Add(const SHRenderable* renderable) noexcept;
void Remove(const SHRenderable* renderable) noexcept; void Remove(const SHRenderable* renderable) noexcept;
void Clear() noexcept; void Clear() noexcept;
void UpdateTransformBuffer(uint32_t frameIndex); void UpdateBuffers(uint32_t frameIndex);
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept; void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept;
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;

View File

@ -150,9 +150,9 @@ namespace SHADE
//compositeSubpass->AddInput("Position"); //compositeSubpass->AddInput("Position");
// TODO: Use macro to add this node when SH_EDITOR is enabled // TODO: Use macro to add this node when SH_EDITOR is enabled
//auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"});
//auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
//imguiSubpass->AddColorOutput("Present"); imguiSubpass->AddColorOutput("Present");
worldRenderGraph->Generate(); worldRenderGraph->Generate();
@ -415,14 +415,19 @@ namespace SHADE
resourceManager.Free(material); resourceManager.Free(material);
} }
Handle<SHMaterialInstance> SHGraphicsSystem::AddMaterialInstance(Handle<SHMaterial> material) Handle<SHMaterialInstance> SHGraphicsSystem::AddOrGetBaseMaterialInstance(Handle<SHMaterial> material)
{ {
return resourceManager.Create<SHMaterialInstance>(material); return materialInstanceCache.CreateOrGet(resourceManager, material);
} }
SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddMaterialInstance() SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddOrGetBaseMaterialInstance()
{ {
return AddMaterialInstance(defaultMaterial); return AddOrGetBaseMaterialInstance(defaultMaterial);
}
SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst)
{
return resourceManager.Create<SHMaterialInstance>(materialInst->GetBaseMaterial());
} }
void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance) void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance)

View File

@ -28,6 +28,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h" #include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h"
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h" #include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
#include "SHMeshLibrary.h" #include "SHMeshLibrary.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
namespace SHADE namespace SHADE
{ {
@ -119,9 +120,10 @@ namespace SHADE
/* Material Creation Functions */ /* Material Creation Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass); Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass);
void RemoveMaterial(Handle<SHMaterial> material);; void RemoveMaterial(Handle<SHMaterial> material);
Handle<SHMaterialInstance> AddMaterialInstance(); Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance();
Handle<SHMaterialInstance> AddMaterialInstance(Handle<SHMaterial> material); Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance); void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -228,8 +230,9 @@ namespace SHADE
Handle<SHGraphicsGlobalData> globalData; Handle<SHGraphicsGlobalData> globalData;
// Middle End Resources // Middle End Resources
ResourceManager resourceManager; ResourceManager resourceManager;
SHMeshLibrary meshLibrary; SHMeshLibrary meshLibrary;
SHMaterialInstanceCache materialInstanceCache;
// Viewports // Viewports
Handle<SHViewport> defaultViewport; // Whole screen Handle<SHViewport> defaultViewport; // Whole screen
std::vector<Handle<SHViewport>> viewports; // Additional viewports std::vector<Handle<SHViewport>> viewports; // Additional viewports

View File

@ -38,7 +38,7 @@ namespace SHADE
dataStore.reset(); dataStore.reset();
} }
void SHMaterialInstance::ExportProperties(void* dest) const void SHMaterialInstance::ExportProperties(void* dest)
{ {
assert(dataStore != nullptr); assert(dataStore != nullptr);
@ -62,6 +62,9 @@ namespace SHADE
const auto DATA_OFFSET = variable->offset; const auto DATA_OFFSET = variable->offset;
memcpy(static_cast<char*>(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize); memcpy(static_cast<char*>(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize);
} }
// Data was exported so unflag
dataWasChanged = false;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -62,12 +62,13 @@ namespace SHADE
template<typename T> template<typename T>
const T& GetProperty(const std::string& key) const; const T& GetProperty(const std::string& key) const;
void ResetProperties() noexcept; void ResetProperties() noexcept;
void ExportProperties(void* dest) const; void ExportProperties(void* dest);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHMaterial> GetBaseMaterial() const { return baseMaterial; } Handle<SHMaterial> GetBaseMaterial() const noexcept { return baseMaterial; }
bool HasChanged() const noexcept { return dataWasChanged; }
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -77,6 +78,7 @@ namespace SHADE
std::vector<OverrideData> overrideData; std::vector<OverrideData> overrideData;
std::unique_ptr<char> dataStore; std::unique_ptr<char> dataStore;
size_t dataStoreSize = 0; size_t dataStoreSize = 0;
bool dataWasChanged = false;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -53,6 +53,9 @@ namespace SHADE
// Save the override data information // Save the override data information
overrideData.emplace_back(std::move(od)); overrideData.emplace_back(std::move(od));
// Flag
dataWasChanged = true;
} }
template<typename T> template<typename T>
T& SHMaterialInstance::GetProperty(const std::string& key) T& SHMaterialInstance::GetProperty(const std::string& key)

View File

@ -81,7 +81,7 @@ namespace SHADE
if (!material) if (!material)
{ {
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
material = gfxSystem->AddMaterialInstance(sharedMaterial->GetBaseMaterial()); material = gfxSystem->AddOrGetBaseMaterialInstance(sharedMaterial->GetBaseMaterial());
} }
return material; return material;

View File

@ -0,0 +1,47 @@
/************************************************************************************//*!
\file SHMaterialInstanceCache.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 25, 2022
\brief Contains the definition of SHMaterialInstanceCache's functions.
Copyright (C) 2022 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.
*//*************************************************************************************/
#include "SHpch.h"
#include "SHMaterialInstanceCache.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Resource/ResourceLibrary.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
SHADE::Handle<SHADE::SHMaterialInstance> SHMaterialInstanceCache::CreateOrGet(ResourceManager& manager, Handle<SHMaterial> material)
{
// Check if there is already an existing instance
auto matInst = cache.find(material);
if (matInst == cache.end())
{
// Create and return
return cache.emplace(material, manager.Create<SHMaterialInstance>(material)).first->second;
}
return matInst->second;
}
void SHMaterialInstanceCache::Remove(Handle<SHMaterial> material)
{
cache.erase(material);
}
void SHMaterialInstanceCache::Clear()
{
cache.clear();
}
}

View File

@ -0,0 +1,93 @@
/************************************************************************************//*!
\file SHMaterialInstanceCache.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 25, 2022
\brief Contains the definition of SHMaterialInstanceCache.
Copyright (C) 2022 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.
*//*************************************************************************************/
#pragma once
// STL Includes
#include <unordered_map>
// Project Includes
#include "Resource/Handle.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHMaterial;
class SHMaterialInstance;
class ResourceManager;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/
/*!
\brief
Creates and caches base SHMaterialInstances. Note that base SHMaterialInstances
refer to SHMaterialInstances with no overrides.
*/
/*************************************************************************************/
class SHMaterialInstanceCache
{
public:
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
\param material
Material to get the SHMaterialInstance for.
\return
Handle to the base SHMaterialInstance that is mapped to SHMaterial.
*/
/***********************************************************************************/
Handle<SHMaterialInstance> CreateOrGet(ResourceManager& manager, Handle<SHMaterial> material);
/***********************************************************************************/
/*!
\brief
Removes a SHMaterialInstance from the cache with a matching material.
\param material
Handle to a SHMaterial that is used to check for removal.
*/
/***********************************************************************************/
void Remove(Handle<SHMaterial> material);
/***********************************************************************************/
/*!
\brief
Removes all SHMaterialInstances in the cache.
*/
/***********************************************************************************/
void Clear();
private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using MaterialMap = std::unordered_map<Handle<SHMaterial>, Handle<SHMaterialInstance>>;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
MaterialMap cache;
};
}

View File

@ -220,7 +220,6 @@ namespace SHADE
, depthReferences{} , depthReferences{}
, inputReferences{} , inputReferences{}
{ {
superBatch = rm.Create<SHSuperBatch>(GetHandle());
} }
/***************************************************************************/ /***************************************************************************/
@ -349,7 +348,7 @@ namespace SHADE
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
{ {
// Ensure correct transforms are provided // Ensure correct transforms are provided
superBatch->UpdateTransformBuffer(frameIndex); superBatch->UpdateBuffers(frameIndex);
// Draw all the batches // Draw all the batches
superBatch->Draw(commandBuffer, frameIndex); superBatch->Draw(commandBuffer, frameIndex);
@ -366,6 +365,12 @@ namespace SHADE
exteriorDrawCalls.push_back(newDrawCall); exteriorDrawCalls.push_back(newDrawCall);
} }
void SHSubpass::Init(ResourceManager& resourceManager) noexcept
{
superBatch = resourceManager.Create<SHSuperBatch>(GetHandle());
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -524,6 +529,9 @@ namespace SHADE
, configured{ rhs.configured } , configured{ rhs.configured }
, executed{ rhs.executed } , executed{ rhs.executed }
, ptrToResources{ rhs.ptrToResources } , ptrToResources{ rhs.ptrToResources }
, pipelineLibrary{ std::move(rhs.pipelineLibrary) }
, batcher { std::move(rhs.batcher) }
{ {
rhs.renderpass = {}; rhs.renderpass = {};
} }
@ -544,6 +552,8 @@ namespace SHADE
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); ptrToResources = std::move(rhs.ptrToResources);
pipelineLibrary = std::move(rhs.pipelineLibrary);
batcher = std::move(rhs.batcher);
rhs.renderpass = {}; rhs.renderpass = {};
@ -577,6 +587,7 @@ namespace SHADE
subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources)); subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
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);
// Register the SuperBatch // Register the SuperBatch
batcher.RegisterSuperBatch(subpass->GetSuperBatch()); batcher.RegisterSuperBatch(subpass->GetSuperBatch());
@ -625,7 +636,7 @@ namespace SHADE
} }
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex) void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex)
{ {
batcher.FinaliseBatches(logicalDeviceHdl, frameIndex); batcher.FinaliseBatches(logicalDeviceHdl, frameIndex);
} }
@ -705,7 +716,7 @@ namespace SHADE
// First we want to take all the attachment descriptions and initialize the // First we want to take all the attachment descriptions and initialize the
// finalLayout to whatever layout is specified in the last subpass that references the attachment. // finalLayout to whatever layout is specified in the last subpass that references the attachment.
for (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 pair (first is initial layout, second is final layout).
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts; std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts;
@ -719,7 +730,7 @@ namespace SHADE
{ {
for (auto& color : subpass->colorReferences) for (auto& color : subpass->colorReferences)
{ {
if (node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) if (i == nodes.size() - 1 && node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR; resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
else else
resourceAttLayouts[color.attachment] = color.layout; resourceAttLayouts[color.attachment] = color.layout;
@ -738,6 +749,7 @@ namespace SHADE
att.initialLayout = vk::ImageLayout::eUndefined; att.initialLayout = vk::ImageLayout::eUndefined;
att.finalLayout = resourceAttLayouts[i]; att.finalLayout = resourceAttLayouts[i];
} }
++i;
} }
// at this point all attachment descs will have their final layouts initialized as if they were standalone and did // at this point all attachment descs will have their final layouts initialized as if they were standalone and did
@ -846,7 +858,7 @@ namespace SHADE
for (auto& inputAtt : subpass->inputReferences) for (auto& inputAtt : subpass->inputReferences)
{ {
auto resource = node->attResources[inputAtt.attachment]; auto resource = node->attResources[inputAtt.attachment];
if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR) if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR || resource->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
colorRead |= (1 << i); colorRead |= (1 << i);
else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL) else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL)
depthRead |= (1 << i); depthRead |= (1 << i);
@ -993,6 +1005,34 @@ namespace SHADE
} }
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
: logicalDeviceHdl{ rhs.logicalDeviceHdl }
, swapchainHdl{ rhs.swapchainHdl }
, nodeIndexing{ std::move(rhs.nodeIndexing) }
, nodes{ std::move(rhs.nodes) }
, graphResources{ std::move(rhs.graphResources) }
, resourceManager{ std::move(rhs.resourceManager) }
, globalData{ rhs.globalData }
{
}
SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept
{
if (&rhs == this)
return *this;
logicalDeviceHdl = rhs.logicalDeviceHdl;
swapchainHdl = rhs.swapchainHdl;
nodeIndexing = std::move(rhs.nodeIndexing);
nodes = std::move(rhs.nodes);
graphResources = std::move(rhs.graphResources);
resourceManager = std::move(rhs.resourceManager);
globalData = rhs.globalData;
return *this;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -1084,7 +1124,7 @@ namespace SHADE
} }
void SHRenderGraph::FinaliseBatch(uint32_t frameIndex) void SHRenderGraph::FinaliseBatch(uint32_t frameIndex)
{ {
for (auto& node : nodes) for (auto& node : nodes)
{ {
node->FinaliseBatch(frameIndex); node->FinaliseBatch(frameIndex);

View File

@ -140,6 +140,8 @@ namespace SHADE
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept; void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
void Init (ResourceManager& resourceManager) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -279,6 +281,8 @@ namespace SHADE
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraph (void) noexcept; SHRenderGraph (void) noexcept;
SHRenderGraph(SHRenderGraph&& rhs) noexcept;
SHRenderGraph& operator=(SHRenderGraph&& rhs) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */

View File

@ -0,0 +1,186 @@
/*********************************************************************
* \file SHInputManagerSystem.cpp
* \author Ryan Wang Nian Jing
* \brief Definition of input manager.
* Handles input from keyboard and mouse. Soon to include controller.
*
* \copyright Copyright (c) 2022 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.
*********************************************************************/
#pragma once
#include <SHpch.h>
#include "SHInputManagerSystem.h"
namespace SHADE
{
/*------------------------------------------------------------------------*/
/* Static defines */
/*------------------------------------------------------------------------*/
unsigned SHInputManagerSystem::keyCount = 0;
bool SHInputManagerSystem::keys[MAX_KEYS];
bool SHInputManagerSystem::keysLast[MAX_KEYS];
double SHInputManagerSystem::keysHeldTime[MAX_KEYS];
double SHInputManagerSystem::keysReleasedTime[MAX_KEYS];
unsigned SHInputManagerSystem::keyToggleCount = 0;
bool SHInputManagerSystem::keysToggle[MAX_KEYS];
bool SHInputManagerSystem::keysToggleLast[MAX_KEYS];
double SHInputManagerSystem::keysToggleOnTime[MAX_KEYS];
double SHInputManagerSystem::keysToggleOffTime[MAX_KEYS];
int SHInputManagerSystem::mouseScreenX = 0;
int SHInputManagerSystem::mouseScreenY = 0;
int SHInputManagerSystem::mouseScreenXLast = 0;
int SHInputManagerSystem::mouseScreenYLast = 0;
double SHInputManagerSystem::mouseVelocityX = 0;
double SHInputManagerSystem::mouseVelocityY = 0;
int SHInputManagerSystem::mouseWheelVerticalDelta = 0;
int SHInputManagerSystem::mouseWheelVerticalDeltaPoll = 0;
void SHInputManagerSystem::Init()
{
keyCount = 0;
SecureZeroMemory(keys, sizeof(keys));
SecureZeroMemory(keysLast, sizeof(keysLast));
SecureZeroMemory(keysHeldTime, sizeof(keysHeldTime));
SecureZeroMemory(keysReleasedTime, sizeof(keysReleasedTime));
keyToggleCount = 0;
SecureZeroMemory(keysToggle, sizeof(keysToggle));
SecureZeroMemory(keysToggleLast, sizeof(keysToggleLast));
SecureZeroMemory(keysToggleOnTime, sizeof(keysToggleOnTime));
SecureZeroMemory(keysToggleOffTime, sizeof(keysToggleOffTime));
mouseScreenX = 0;
mouseScreenY = 0;
mouseScreenXLast = 0;
mouseScreenYLast = 0;
mouseWheelVerticalDelta = 0;
mouseWheelVerticalDeltaPoll = 0;
}
void SHInputManagerSystem::Exit()
{
//No dynamically allocated memory. Nothing to do here.
}
void SHInputManagerSystem::InputManagerRoutine::
FixedExecute(double dt) noexcept
{
//Keyboard and Mouse Buttons////////////////////////////////////////////////
//Poll
unsigned char keyboardState[MAX_KEYS];
GetKeyboardState(keyboardState);
keyCount = 0;
keyToggleCount = 0;
for (size_t i = 0; i < MAX_KEYS; ++i)
{
//Ignore shift, ctrl and alt since they are split to left and right
if (static_cast<SH_KEYCODE>(i) == SH_KEYCODE::SHIFT ||
static_cast<SH_KEYCODE>(i) == SH_KEYCODE::CTRL ||
static_cast<SH_KEYCODE>(i) == SH_KEYCODE::ALT)
continue;
//Pressed state
if (keyboardState[i] & 0b10000000)
{
++keyCount;
keys[i] = true;
}
else keys[i] = false;
//Toggle state
if (keyboardState[i] & 0b00000001)
{
++keyToggleCount;
keysToggle[i] = true;
}
else keysToggle[i] = false;
}
//Timers
for (size_t i = 0; i < MAX_KEYS; ++i)
{
if (keys[i]) //Key is down
{
if (!keysLast[i]) //Key was just pressed
{
keysHeldTime[i] = 0.0; //Reset timer
}
keysHeldTime[i] += dt; //Tick up
}
else //Key is up
{
if (keysLast[i]) //Key was just released
{
keysReleasedTime[i] = 0.0; //Reset timer
}
keysReleasedTime[i] += dt; //Tick up
}
}
//Write to lastKeys
memcpy(keysLast, keys, sizeof(keys));
//Mouse Positioning/////////////////////////////////////
//https://stackoverflow.com/a/6423739
//Set last positioning
mouseScreenXLast = mouseScreenX;
mouseScreenYLast = mouseScreenY;
//Get cursor position, even when it is outside window
POINT p;
GetCursorPos(&p);
mouseScreenX = p.x;
mouseScreenY = p.y;
//Mouse wheel vertical delta updating
mouseWheelVerticalDelta = 0;
mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll;
mouseWheelVerticalDeltaPoll = 0;
}
bool SHInputManagerSystem::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept
{
for (size_t i = 0; i < MAX_KEYS; ++i)
{
if (keys[i] && !keysLast[i])
{
if (firstDetected) *firstDetected = static_cast<SH_KEYCODE>(i);
return true;
}
}
return false;
}
bool SHInputManagerSystem::AnyKey(SH_KEYCODE* firstDetected) noexcept
{
for (size_t i = 0; i < MAX_KEYS; ++i)
{
if (keys[i])
{
if (firstDetected) *firstDetected = static_cast<SH_KEYCODE>(i);
return true;
}
}
return false;
}
bool SHInputManagerSystem::AnyKeyUp(SH_KEYCODE* firstDetected) noexcept
{
for (size_t i = 0; i < MAX_KEYS; ++i)
{
if (!keys[i] && keysLast[i])
{
if (firstDetected) *firstDetected = static_cast<SH_KEYCODE>(i);
return true;
}
}
return false;
}
} //namespace SHADE

View File

@ -0,0 +1,580 @@
/*********************************************************************
* \file SHInputManagerSystem.h
* \author Ryan Wang Nian Jing
* \brief Declaration of input manager.
* Handles input from keyboard and mouse. Soon to include controller.
*
* \copyright Copyright (c) 2022 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.
*********************************************************************/
#pragma once
//#include <Xinput.h>
//#include "../../SHADE_Managed/src/SHpch.h"
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHFixedSystemRoutine.h"
namespace SHADE
{
class SH_API SHInputManagerSystem : public SHSystem
{
public:
class SH_API InputManagerRoutine : public SHFixedSystemRoutine
{
public:
virtual void FixedExecute(double dt) noexcept override final;
};
public:
/*------------------------------------------------------------------------*/
/* Enumerations */
/*------------------------------------------------------------------------*/
enum class SH_KEYCODE
{
LMB = 0X01,
RMB = 0X02,
CANCEL = 0X03,
MMB = 0X04,
XMB1 = 0X05,
XMB2 = 0X06,
BACKSPACE = 0X08,
TAB = 0X09,
CLEAR = 0X0C,
ENTER = 0X0D,
SHIFT = 0X10, //USE LEFT OR RIGHT SHIFT INSTEAD
CTRL = 0X11, //USE LEFT OR RIGHT CTRL INSTEAD
ALT = 0X12, //USE LEFT OR RIGHT ALT INSTEAD
PAUSE = 0X13,
CAPS_LOCK = 0X14,
IME_KANA = 0X15,
IME_HANGUL = 0X15,
IME_ON = 0X16,
IME_JUNJA = 0X17,
IME_FINAL = 0X18,
IME_HANJA = 0X19,
IME_KANJI = 0X19,
IME_OFF = 0X1A,
ESCAPE = 0X1B,
IME_CONVERT = 0X1C,
IME_NONCONVERT = 0X1D,
IME_ACCEPT = 0X1E,
IME_MODECHANGE = 0X1F,
SPACE = 0X20,
PAGE_UP = 0X21,
PAGE_DOWN = 0X22,
END = 0X23,
HOME = 0X24,
LEFT_ARROW = 0X25,
UP_ARROW = 0X26,
RIGHT_ARROW = 0X27,
DOWN_ARROW = 0X28,
SELECT = 0X29,
PRINT = 0X2A,
EXECUTE = 0X2B,
PRINT_SCREEN = 0X2C,
INSERT = 0X2D,
DEL = 0X2E,
HELP = 0X2F,
NUMBER_0 = 0X30,
NUMBER_1,
NUMBER_2,
NUMBER_3,
NUMBER_4,
NUMBER_5,
NUMBER_6,
NUMBER_7,
NUMBER_8,
NUMBER_9,
A = 0X41,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
LEFT_WINDOWS = 0X5B,
RIGHT_WINDOWS,
APPS,
SLEEP = 0X5F,
NUMPAD_0 = 0X60,
NUMPAD_1,
NUMPAD_2,
NUMPAD_3,
NUMPAD_4,
NUMPAD_5,
NUMPAD_6,
NUMPAD_7,
NUMPAD_8,
NUMPAD_9,
MULTIPLY = 0X6A,
ADD,
SEPARATOR,
SUBTRACT,
DECIMAL,
DIVIDE,
F1 = 0X70,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
NUM_LOCK = 0X90,
SCROLL_LOCK = 0X91,
OEM_PC98_NUMPAD_EQUAL = 0X92,
OEM_FUJITSU_DICTIONARY = 0X92,
OEM_FUJITSU_UNREGISTER,
OEM_FUJITSU_REGISTER,
OEM_FUJITSU_LEFT_THUMB,
OEM_FUJITSU_RIGHT_THUMB,
LEFT_SHIFT = 0XA0,
RIGHT_SHIFT,
LEFT_CTRL,
RIGHT_CTRL,
LEFT_ALT,
RIGHT_ALT,
BROWSER_BACK,
BROWSER_FORWARD,
BROWSER_REFRESH,
BROWSER_STOP,
BROWSER_SEARCH,
BROWSER_FAVOURITES,
BROWSER_HOME,
VOLUME_MUTE,
VOLUME_DOWN,
VOLUME_UP,
MEDIA_NEXT_TRACK,
MEDIA_PREVIOUS_TRACK,
MEDIA_STOP,
MEDIA_PLAY_PAUSE,
LAUNCH_MAIL,
LAUNCH_MEDIA_SELECT,
LAUNCH_APP_1,
LAUNCH_APP_2,
OEM_1 = 0XBA,
OEM_PLUS,
OEM_COMMA,
OEM_MINUS,
OEM_PERIOD,
OEM_2,
OEM_3,
GAMEPAD_A = 0XC3,
GAMEPAD_B,
GAMEPAD_X,
GAMEPAD_Y,
GAMEPAD_RIGHTSHOULDER,
GAMEPAD_LEFTSHOULDER,
GAMEPAD_LEFTTRIGGER,
GAMEPAD_RIGHTTRIGGER,
GAMEPAD_DPAD_UP,
GAMEPAD_DPAD_DOWN,
GAMEPAD_DPAD_LEFT,
GAMEPAD_DPAD_RIGHT,
GAMEPAD_MENU,
GAMEPAD_VIEW,
GAMEPAD_LEFT_THUMBSTICK_BUTTON,
GAMEPAD_RIGHT_THUMBSTICK_BUTTON,
GAMEPAD_LEFT_THUMBSTICK_UP,
GAMEPAD_LEFT_THUMBSTICK_DOWN,
GAMEPAD_LEFT_THUMBSTICK_RIGHT,
GAMEPAD_LEFT_THUMBSTICK_LEFT,
GAMEPAD_RIGHT_THUMBSTICK_UP,
GAMEPAD_RIGHT_THUMBSTICK_DOWN,
GAMEPAD_RIGHT_THUMBSTICK_RIGHT,
GAMEPAD_RIGHT_THUMBSTICK_LEFT,
OEM_4,
OEM_5,
OEM_6,
OEM_7,
OEM_8,
OEM_AX = 0XE1,
OEM_102,
OEM_ICO_HELP,
OEM_ICO_00,
IME_PROCESS,
OEM_ICO_CLEAR,
PACKET,
OEM_RESET = 0XE9,
OEM_JUMP,
OEM_PA1,
OEM_PA2,
OEM_PA3,
OEM_WSCTRL,
OEM_CUSEL,
OEM_ATTN,
OEM_FINISH,
OEM_COPY,
OEM_AUTO,
OEM_ENLW,
OEM_BACKTAB,
ATTN,
CRSEL,
EXSEL,
EREOF,
PLAY,
ZOOM,
NONAME,
PA_1,
OEM_CLEAR
};
public:
/*------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*------------------------------------------------------------------------*/
SHInputManagerSystem() noexcept = default;
~SHInputManagerSystem() noexcept = default;
SHInputManagerSystem(const SHInputManagerSystem&) = delete;
SHInputManagerSystem(SHInputManagerSystem&&) = delete;
SHInputManagerSystem& operator= (const SHInputManagerSystem&) = delete;
SHInputManagerSystem& operator= (SHInputManagerSystem&&) = delete;
/*------------------------------------------------------------------------*/
/* SHSystem Overrides */
/*------------------------------------------------------------------------*/
virtual void Init() override final;
virtual void Exit() override final;
/*------------------------------------------------------------------------*/
/* Member Functions */
/*------------------------------------------------------------------------*/
//Needs to be linked to WM_MOUSEWHEEL in wndProc
static inline void PollWheelVerticalDelta(WPARAM wParam) noexcept
{
mouseWheelVerticalDeltaPoll += GET_WHEEL_DELTA_WPARAM(wParam);
}
//For testing purposes
//static void PrintCurrentState() noexcept;
/*------------------------------------------------------------------------*/
/* Input state accessors (KB & M) */
/*------------------------------------------------------------------------*/
//Get how many keys are presently down
static inline unsigned GetKeyCount() noexcept
{
return keyCount;
}
//How many keys are presently toggled
static inline unsigned GetKeyToggleCount() noexcept
{
return keyToggleCount;
}
//Any key pressed in THIS FRAME ONLY
//Keys being held beforehand don't count
//Output parameter is which key was first to be detected
static bool AnyKeyDown(SH_KEYCODE* firstKey = nullptr) noexcept;
//Any key is being held down
//Return false if no key being held
//Output parameter is which key was first to be detected
static bool AnyKey(SH_KEYCODE* firstKey = nullptr) noexcept;
//Any key released in THIS FRAME ONLY
//Keys that are released beforehand don't count
//Output parameter is which key was first to be detected
static bool AnyKeyUp(SH_KEYCODE* firstKey = nullptr) noexcept;
//Check if a particular key was pressed down in THIS FRAME ONLY
//Keys being held beforehand don't count
//Output parameter is how long the key has been released for prior
static inline bool GetKeyDown (SH_KEYCODE key,
double* releasedTime = nullptr) noexcept
{
if (releasedTime) *releasedTime = keysReleasedTime[static_cast<int>(key)];
return (keys[static_cast<int>(key)] && !keysLast[static_cast<int>(key)]);
}
//Check if a particular key was toggled on in THIS FRAME ONLY
//Keys that stay toggled on afterwards don't count
//Output parameter is how long the key has been toggled off for prior
static inline bool GetKeyToggleOn (SH_KEYCODE key,
double* toggleOffTime = nullptr) noexcept
{
if (toggleOffTime)
*toggleOffTime = keysToggleOffTime[static_cast<int>(key)];
return (keysToggle[static_cast<int>(key)] &&
!keysToggleLast[static_cast<int>(key)]);
}
//Check if a particular key is presently being held down on
//Output parameter is how long the key has been held and released
static inline bool GetKey(SH_KEYCODE key,
double* heldTime = nullptr, double* releasedTime = nullptr) noexcept
{
if (heldTime) *heldTime = keysHeldTime[static_cast<int>(key)];
if (releasedTime) *releasedTime = keysReleasedTime[static_cast<int>(key)];
return keys[static_cast<int>(key)];
}
//Check if a particular key is presently toggled on
//Output parameter is how long the key has been toggled on and off
static inline bool GetKeyToggle(SH_KEYCODE key,
double* onTime = nullptr, double* offTime = nullptr) noexcept
{
if (onTime) *onTime = keysToggleOnTime[static_cast<int>(key)];
if (offTime) *offTime = keysToggleOffTime[static_cast<int>(key)];
return keysToggle[static_cast<int>(key)];
}
//Check if a particular key was released in THIS FRAME ONLY
//Keys already released beforehand don't count
//Output parameter is how long the key has been held for prior
static inline bool GetKeyUp(SH_KEYCODE key,
double* heldTime = nullptr) noexcept
{
if (heldTime) *heldTime = keysHeldTime[static_cast<int>(key)];
return (!keys[static_cast<int>(key)] && keysLast[static_cast<int>(key)]);
}
//Check if a particular key was toggled off in THIS FRAME ONLY
//Keys that stay toggled off afterwards don't count
//Output parameter is how long the key has been toggled on for prior
static inline bool GetKeyToggleOff(SH_KEYCODE key,
double* toggleOnTime = nullptr) noexcept
{
if (toggleOnTime)
*toggleOnTime = keysToggleOnTime[static_cast<int>(key)];
return (!keysToggle[static_cast<int>(key)] &&
keysToggleLast[static_cast<int>(key)]);
}
//Mouse/////////////
//Get the mouse location with respect to the screen
static inline void GetMouseScreenPosition (int* x = nullptr,
int* y = nullptr) noexcept
{
if (x) *x = mouseScreenX;
if (y) *y = mouseScreenY;
}
//Get the mouse location with respect to current window
static inline void GetMouseWindowPosition (int* x = nullptr,
int* y = nullptr) noexcept
{
POINT p{ mouseScreenX, mouseScreenY };
ScreenToClient(GetActiveWindow(), &p);
if (x) *x = mouseScreenX;
if (y) *y = mouseScreenY;
}
//Get the mouse velocity
//Two output parameters for x and y velocitites
//In pixels per second for both
static inline void GetMouseVelocity(double* x = nullptr,
double* y = nullptr) noexcept
{
if (x) *x = mouseVelocityX;
if (y) *y = mouseVelocityY;
}
//Get the mouse wheel vertical delta
static inline int GetMouseWheelVerticalDelta() noexcept
{
return mouseWheelVerticalDelta;
}
//GET INPUT TIMINGS///////////////////////////////////////////////////////////
//Keyboard/////////////
//How long has this key been held down for
static inline double GetKeyHeldTime(SH_KEYCODE key) noexcept
{
return keysHeldTime[static_cast<int>(key)];
}
//How long has this key been released for
static inline double GetKeyReleasedTime(SH_KEYCODE key) noexcept
{
return keysReleasedTime[static_cast<int>(key)];
}
//How long has this key been toggled on for
static inline double GetKeyToggleOnTime(SH_KEYCODE key) noexcept
{
return keysToggleOnTime[static_cast<int>(key)];
}
//How long has this keen been toggled off for
static inline double GetKeyToggleOffTime(SH_KEYCODE key) noexcept
{
return keysToggleOffTime[static_cast<int>(key)];
}
/*------------------------------------------------------------------------*/
/* Other Functions */
/*------------------------------------------------------------------------*/
//Mouse////////////////////////
//Move mouse cursor to a position on the screen
static inline void SetMouseScreenPosition(int x = 0, int y = 0) noexcept
{
SetCursorPos(x, y);
}
//Move mouse cursor to a position on the active window
static inline void SetMouseWindowPosition(int x = 0, int y = 0) noexcept
{
POINT p{ x, y };
ClientToScreen(GetActiveWindow(), &p);
SetCursorPos(p.x, p.y);
}
private:
/*------------------------------------------------------------------------*/
/* Constants */
/*------------------------------------------------------------------------*/
static constexpr size_t MAX_KEYS = UCHAR_MAX + 1;
/*------------------------------------------------------------------------*/
/* Data Members */
/*------------------------------------------------------------------------*/
//KEYBOARD AND MOUSE BUTTONS////////////////////////////////////////////////
//How many keys are presently being pressed
static unsigned keyCount;
//Key states of all keys presently
//true for being pressed, false for released
static bool keys[MAX_KEYS];
//Key states of all keys in the last frame
//true for being pressed, false for released
static bool keysLast[MAX_KEYS];
//Key held durations
//Stops ticking up when released
//Will be reset when held again
static double keysHeldTime[MAX_KEYS];
//Key released durations
//Stops ticking up when held
//Will be reset when off again
static double keysReleasedTime[MAX_KEYS];
//How many keys are presently being toggled
static unsigned keyToggleCount;
//Toggle key states of keys (not neccessarily just caps/num/scroll locks)
static bool keysToggle[MAX_KEYS];
//Toggle key states of keys in the last frame
static bool keysToggleLast[MAX_KEYS];
//Key toggle durations
//Stops ticking up when untoggled
//Will be reset when toggled again
static double keysToggleOnTime[MAX_KEYS];
//Key untoggle durations
//Stops ticking up when toggled
//Will be reset when untoggled again
static double keysToggleOffTime[MAX_KEYS];
//MOUSE VARIABLES///////////////////////////////////////////////////////////
//Present horizontal positioning of the mouse WRT the screen
//Increasing rightwards
static int mouseScreenX;
//Present vertical positioning of the mouse WRT the screen
//Increasing downwards
static int mouseScreenY;
//Horizontal positioning of the mouse WRT screen in last frame
//Increasing rightwards
static int mouseScreenXLast;
//Vertical positioning of the mouse WRT screen in the last frame
//Increasing downwards
static int mouseScreenYLast;
//The velocity at which the mouse is being moved horizontally (px/s)
//Rightwards is positive
static double mouseVelocityX;
//The velocity at which the mouse is being moved vertically (px/s)
//Downwards is positive
static double mouseVelocityY;
//For polling mouse wheel events, not to be read
static int mouseWheelVerticalDeltaPoll;
//Mouse wheel vertical rotation speed. Positive is rotation AWAY from user
static int mouseWheelVerticalDelta;
//CONTROLLER VARIABLES//////////////////////////////////////////////////////
//OTHER VARIABLES///////////////////////////////////////////////////////////
//Axis bindings
//X
//Y
//Other mappings
//Buffer
};
}