diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 938b0b57..7ef8adfe 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -23,8 +23,10 @@ #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Scene/SHSceneManager.h" #include "Math/Transform/SHTransformSystem.h" +#include "Input/SHInputManagerSystem.h" #include "Scenes/SBTestScene.h" +#include "Math/Transform/SHTransformComponent.h" using namespace SHADE; @@ -51,6 +53,7 @@ namespace Sandbox SHADE::SHSystemManager::CreateSystem(); SHADE::SHSystemManager::CreateSystem(); SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); + SHADE::SHSystemManager::CreateSystem(); // Create Routines SHADE::SHSystemManager::RegisterRoutine(); @@ -67,8 +70,12 @@ namespace Sandbox SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); - SHADE::SHComponentManager::CreateComponentSparseSet(); + SHADE::SHComponentManager::CreateComponentSparseSet(); + SHADE::SHComponentManager::CreateComponentSparseSet(); + + SHADE::SHSystemManager::RegisterRoutine(); + // Set up graphics system and windows graphicsSystem->SetWindow(&window); sdlWindow = SDL_CreateWindowFrom(window.GetHWND()); diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 751e17a8..fc2f9731 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -36,26 +36,58 @@ namespace Sandbox graphicsSystem->BuildMeshBuffers(); // Create Materials - auto matInst = graphicsSystem->AddMaterialInstance(); + auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance(); - // Create entity and add mesh - testObj = SHADE::SHEntityManager::CreateEntity(); - auto& renderable = *SHADE::SHComponentManager::GetComponent_s(testObj); - renderable.Mesh = CUBE_MESH; - renderable.SetMaterial(matInst); - // Create transform - auto& transform = *SHADE::SHComponentManager::GetComponent_s(testObj); - transform.SetLocalPosition(SHVec3{ 0.0f, 0.0f, 2.0f }); + // Create Stress Test Objects + static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f }; + constexpr int NUM_ROWS = 1; + constexpr int NUM_COLS = 1; + static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f }; + static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f }; + for (int z = 0; z < NUM_ROWS; ++z) + for (int x = 0; x < NUM_COLS; ++x) + { + auto entity = SHEntityManager::CreateEntity(); + auto& renderable = *SHComponentManager::GetComponent_s(entity); + auto& transform = *SHComponentManager::GetComponent_s(entity); - renderable.TransformMatrix = SHMatrix::Translate(0.0f, 0.0f, 2.0f); + renderable.Mesh = CUBE_MESH; + renderable.SetMaterial(matInst); + + // Set initial positions + transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, 0.0f, z * TEST_OBJ_SPACING.z }); + //transform.SetLocalScale(TEST_OBJ_SCALE); + + stressTestObjects.emplace_back(entity); + } + + // Create blank entity with a script + testObj = SHADE::SHEntityManager::CreateEntity(); SHADE::SHScriptEngine* scriptEngine = static_cast(SHADE::SHSystemManager::GetSystem()); - scriptEngine->AddScript(*SHADE::SHEntityManager::GetEntityByID(testObj), "TestScript"); + scriptEngine->AddScript(testObj, "TestScript"); } + void SBTestScene::Update(float dt) { - (void)dt; + /*static float rotation = 0.0f; + + auto& transform = *SHADE::SHComponentManager::GetComponent_s(testObj); + + transform.SetLocalRotation(rotation, 0.0f, 0.0f); + rotation += dt * 10.0f;*/ + /*static float rotation = 0.0f; + + auto& transform = *SHADE::SHComponentManager::GetComponent_s(stressTestObjects[0]); + + transform.SetWorldPosition({rotation, 0.0f, 0.0f}); + rotation += dt * 10.0f;*/ + + // Destroy entity if space is pressed if (GetKeyState(VK_SPACE) & 0x8000) - SHADE::SHEntityManager::DestroyEntity(testObj); + { + SHADE::SHScriptEngine* scriptEngine = static_cast(SHADE::SHSystemManager::GetSystem()); + scriptEngine->RemoveAllScripts(testObj); + } } void SBTestScene::Render() diff --git a/SHADE_Application/src/Scenes/SBTestScene.h b/SHADE_Application/src/Scenes/SBTestScene.h index 4d4a3207..3a1598d5 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.h +++ b/SHADE_Application/src/Scenes/SBTestScene.h @@ -10,7 +10,7 @@ namespace Sandbox private: EntityID camera; EntityID testObj; - + std::vector stressTestObjects; public: virtual void Load(); diff --git a/SHADE_Engine/NatvisFile.natvis b/SHADE_Engine/NatvisFile.natvis new file mode 100644 index 00000000..6747262b --- /dev/null +++ b/SHADE_Engine/NatvisFile.natvis @@ -0,0 +1,10 @@ + + + + NULL + ID = {id.Data.Index} Version = {id.Data.Version} Type = {"$T1"} + + (*library).objects.denseArray[(*library).objects.sparseArray[id.Data.Index]] + + + \ No newline at end of file diff --git a/SHADE_Engine/premake5.lua b/SHADE_Engine/premake5.lua index 84acd8fa..2e6c39f9 100644 --- a/SHADE_Engine/premake5.lua +++ b/SHADE_Engine/premake5.lua @@ -15,7 +15,8 @@ project "SHADE_Engine" "%{prj.location}/src/**.hpp", "%{prj.location}/src/**.c", "%{prj.location}/src/**.cpp", - "%{prj.location}/src/**.glsl" + "%{prj.location}/src/**.glsl", + "%{prj.location}/**.natvis" } includedirs diff --git a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp index 4bfc1e4b..da4bc292 100644 --- a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp @@ -49,6 +49,11 @@ namespace SHADE Init(newSize, data, srcSize, bufferUsageFlags, allocCreateInfo.usage, allocCreateInfo.flags); } + void SHVkBuffer::FlushAllocation(uint32_t srcOffset, uint32_t dstOffset) noexcept + { + vmaFlushAllocation(vmaAllocator, alloc, srcOffset, dstOffset); + } + vk::Buffer SHVkBuffer::GetVkBuffer(void) const noexcept { return vkBuffer; @@ -72,8 +77,7 @@ namespace SHADE /***************************************************************************/ void SHVkBuffer::Map(void) noexcept { - if (!boundToCoherent) - vmaMapMemory(vmaAllocator, alloc, &mappedPtr); + vmaMapMemory(vmaAllocator, alloc, &mappedPtr); } /***************************************************************************/ @@ -90,11 +94,8 @@ namespace SHADE /***************************************************************************/ void SHVkBuffer::Unmap(void) noexcept { - if (!boundToCoherent) - { - vmaUnmapMemory(vmaAllocator, alloc); - mappedPtr = nullptr; - } + vmaUnmapMemory(vmaAllocator, alloc); + mappedPtr = nullptr; } /***************************************************************************/ @@ -132,9 +133,7 @@ namespace SHADE Otherwise, only the copying is carried out. In the instance where memory is non-coherent but HOST_VISIBLE, we want to - write to data and then unmap and flush it immediately. If you want to write - to memory in random-access fashion, consider, mapping, writing a few - things, unmapping then flushing. + write to data and then unmap and flush it immediately. \param vmaAllocator The VMA allocator object. @@ -155,18 +154,11 @@ namespace SHADE /***************************************************************************/ void SHVkBuffer::MapWriteUnmap(void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept { - if (!boundToCoherent) - { - // map from host visible memory to pointer, do a DMA, and then unmap - Map(); - WriteToMemory(data, sizeToWrite, srcOffset, dstOffset); - Unmap(); - } - else - { - if (mappedPtr) - std::memcpy(static_cast(mappedPtr) + dstOffset, static_cast(data) + srcOffset, sizeToWrite); - } + // map from host visible memory to pointer, do a DMA, and then unmap + Map(); + WriteToMemory(data, sizeToWrite, srcOffset, dstOffset); + Unmap(); + FlushAllocation(srcOffset, dstOffset); } /***************************************************************************/ @@ -279,7 +271,6 @@ namespace SHADE , mappedPtr{ nullptr } , alloc {nullptr} , randomAccessOptimized{false} - , boundToCoherent {false} , vmaAllocator{allocator} {} @@ -304,7 +295,6 @@ namespace SHADE , mappedPtr{ std::move(rhs.mappedPtr) } , alloc{ std::move (rhs.alloc) } , randomAccessOptimized{ rhs.randomAccessOptimized } - , boundToCoherent{ rhs.boundToCoherent} , vmaAllocator{ rhs.vmaAllocator } , bufferUsageFlags {rhs.bufferUsageFlags} , bufferCreateInfo { rhs.bufferCreateInfo } @@ -325,7 +315,6 @@ namespace SHADE mappedPtr = std::move(rhs.mappedPtr); alloc = std::move(rhs.alloc); randomAccessOptimized = rhs.randomAccessOptimized; - boundToCoherent = rhs.boundToCoherent; vmaAllocator = std::move (rhs.vmaAllocator); rhs.vkBuffer = VK_NULL_HANDLE; bufferCreateInfo = rhs.bufferCreateInfo; @@ -430,18 +419,20 @@ namespace SHADE // mainly host visible. Can be cached (need to flush/invalidate), uncached (always coherent) and coherent (virtual). if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - // If memory is marked to be coherent between CPU and GPU (no need flush/invalidate) (TODO: Verify if VMA_ALLOCATION_CREATE_MAPPED_BIT is used when VMA_MEMORY_USAGE_AUTO is set) - // TODO: also verify that coherent bit = pointer is already mapped - if (memPropFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) - { - boundToCoherent = true; + const bool CREATE_MAPPED = allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT; + + if (CREATE_MAPPED) mappedPtr = allocInfo.pMappedData; - } else mappedPtr = nullptr; if (data) - MapWriteUnmap(data, srcSize, 0, 0); + { + if (CREATE_MAPPED) + WriteToMemory(data, srcSize, 0, 0); + else + MapWriteUnmap(data, srcSize, 0, 0); + } } else { diff --git a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h index 49f22e37..648a07e8 100644 --- a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h +++ b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h @@ -41,9 +41,6 @@ namespace SHADE //! If initialized with vma random access flag, this is true bool randomAccessOptimized; - //! Whether or not this buffer is bound to coherent memory - bool boundToCoherent; - //! buffer usage info flags vk::BufferUsageFlags bufferUsageFlags; @@ -100,6 +97,7 @@ namespace SHADE void TransferToDeviceResource(Handle const& cmdBufferHdl) noexcept; void ResizeNoCopy (uint32_t newSize); void ResizeReplace (uint32_t newSize, void* data, uint32_t srcSize); + void FlushAllocation (uint32_t srcOffset, uint32_t dstOffset) noexcept; /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index 6898b7e0..eb65598c 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp @@ -8,6 +8,7 @@ #include "Graphics/Framebuffer/SHVkFramebuffer.h" #include "Graphics/Pipeline/SHVkPipeline.h" #include "Graphics/Buffers/SHVkBuffer.h" +#include "Graphics/Images/SHVkImage.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" @@ -15,7 +16,7 @@ namespace SHADE { /***************************************************************************/ /*! - + \brief Frees the command buffer. @@ -29,13 +30,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief - Only the command buffer is allocated using - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit, is resetting + Only the command buffer is allocated using + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit, is resetting individually permitted. Otherwise, throw exception. IMPORTANT NOTE: the command buffer cannot be in the pending state!!! - + */ /***************************************************************************/ void SHVkCommandBuffer::Reset(void) @@ -66,10 +67,10 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Begins the command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::BeginRecording(void) noexcept @@ -107,10 +108,10 @@ namespace SHADE /***************************************************************************/ /*! - + \brief End the recording of a command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::EndRecording(void) noexcept @@ -120,21 +121,21 @@ namespace SHADE SHLOG_ERROR("Command Buffer not in recording state, cannot end recording. "); return; } - + vkCommandBuffer.end(); cmdBufferState = SH_CMD_BUFFER_STATE::EXECUTABLE; } /***************************************************************************/ /*! - + \brief - Begins a renderpass in the command buffer. 2 important things to note - here, the command buffer used MUST be a primary command buffer and + Begins a renderpass in the command buffer. 2 important things to note + here, the command buffer used MUST be a primary command buffer and command buffer MUST be in a recording state. - + \param renderpassHdl - Renderpass for obvious reasons. + Renderpass for obvious reasons. \param framebufferHdl Framebuffer required in the begin info. @@ -144,7 +145,7 @@ namespace SHADE \param extent Extent of the render area in the framebuffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::BeginRenderpass(Handle const& renderpassHdl, Handle const& framebufferHdl, vk::Offset2D offset, vk::Extent2D extent) noexcept @@ -169,7 +170,7 @@ namespace SHADE vk::RenderPassBeginInfo renderPassInfo{}; renderPassInfo.renderPass = renderpassHdl->GetVkRenderpass(); renderPassInfo.framebuffer = framebufferHdl->GetVkFramebuffer(); - + // If the extent passed in is 0, use the framebuffer dimensions instead. if (extent.width == 0 && extent.height == 0) renderPassInfo.renderArea.extent = framebufferExtent; @@ -191,16 +192,16 @@ namespace SHADE } // Begin the render pass - vkCommandBuffer.beginRenderPass (&renderPassInfo, vk::SubpassContents::eInline); + vkCommandBuffer.beginRenderPass(&renderPassInfo, vk::SubpassContents::eInline); } /***************************************************************************/ /*! - + \brief Ends a renderpass. - + */ /***************************************************************************/ void SHVkCommandBuffer::EndRenderpass(void) noexcept @@ -215,14 +216,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Sets the viewport dynamically for the command buffer. #NoteToSelf: 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 this only needs to happen ONCE per command buffer UNLESS a different viewport is to be used for different drawing commands. - + \param vpWidth viewport width @@ -253,7 +254,7 @@ namespace SHADE \param vpMaxDepth 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 @@ -282,13 +283,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Binds a pipeline object to the command buffer. - + \param pipelineHdl The pipeline to bind. - + */ /***************************************************************************/ void SHVkCommandBuffer::BindPipeline(Handle const& pipelineHdl) noexcept @@ -306,7 +307,7 @@ namespace SHADE /*! \brief - Binds a buffer to the vertex buffer binding point specified in + Binds a buffer to the vertex buffer binding point specified in bindingPoint. \param bindingPoint @@ -320,29 +321,32 @@ namespace SHADE */ /***************************************************************************/ - void SHVkCommandBuffer::BindVertexBuffer (uint32_t bindingPoint, Handle const& buffer, vk::DeviceSize offset) noexcept + void SHVkCommandBuffer::BindVertexBuffer(uint32_t bindingPoint, Handle const& buffer, vk::DeviceSize offset) noexcept { if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) { - auto bufferHandle = buffer->GetVkBuffer(); - vkCommandBuffer.bindVertexBuffers (bindingPoint, 1, &bufferHandle, &offset); + if (buffer) + { + auto bufferHandle = buffer->GetVkBuffer(); + vkCommandBuffer.bindVertexBuffers(bindingPoint, 1, &bufferHandle, &offset); + } } } /***************************************************************************/ /*! - + \brief Binds an index buffer to the pipeline. - + \param buffer The buffer to bind. \param startingIndex - The starting index in the index buffer. For example, 0 would mean - starting at the beginning. 5 would mean starting at byte offset + The starting index in the index buffer. For example, 0 would mean + starting at the beginning. 5 would mean starting at byte offset size(uint32_t) * 5. - + */ /***************************************************************************/ void SHVkCommandBuffer::BindIndexBuffer(Handle const& buffer, uint32_t startingIndex) const noexcept @@ -350,33 +354,33 @@ namespace SHADE if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) { 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 descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span dynamicOffsets) { - vkCommandBuffer.bindDescriptorSets (bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); + vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); } /***************************************************************************/ /*! - + \brief Calls vkCmdDraw. - + \param vertexCount How many vertices to draw \param instanceCount Number of instances to draw - + \param firstVertex First vertex in the buffer of vertices to start from \param firstInstance First instance to start from. - + */ /***************************************************************************/ void SHVkCommandBuffer::DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept @@ -386,30 +390,30 @@ namespace SHADE SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. "); return; } - vkCommandBuffer.draw (vertexCount, instanceCount, firstVertex, firstInstance); + vkCommandBuffer.draw(vertexCount, instanceCount, firstVertex, firstInstance); } /***************************************************************************/ /*! - + \brief Issues a non-instanced indexed draw call. - + \param indexCount Number of indices to draw. \param firstIndex 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 - 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 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) { @@ -422,41 +426,6 @@ namespace SHADE } - - void SHVkCommandBuffer::PipelineBarrier ( - vk::PipelineStageFlags srcStage, - vk::PipelineStageFlags dstStage, - vk::DependencyFlags deps, - std::vector const& memoryBarriers, - std::vector const& bufferMemoryBarriers, - std::vector const& imageMemoryBarriers - ) const noexcept - { - vkCommandBuffer.pipelineBarrier ( - srcStage, - dstStage, - deps, - memoryBarriers, - bufferMemoryBarriers, - imageMemoryBarriers - ); - } - - bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept - { - return cmdBufferState == SH_CMD_BUFFER_STATE::EXECUTABLE; - } - - void SHVkCommandBuffer::HandlePostSubmit(void) noexcept - { - SetState(SH_CMD_BUFFER_STATE::PENDING); - } - - //void SHVkCommandBuffer::PipelineBarrier(vk::PipelineStageFlags ) const noexcept - //{ - // //vkCommandBuffer.pipelineBarrier() - //} - /***************************************************************************/ /*! @@ -479,17 +448,64 @@ namespace SHADE 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& copyInfo) + { + vkCommandBuffer.copyBufferToImage + ( + src, dst, vk::ImageLayout::eTransferDstOptimal, + static_cast(copyInfo.size()), copyInfo.data() + ); + } + void SHVkCommandBuffer::PipelineBarrier( + vk::PipelineStageFlags srcStage, + vk::PipelineStageFlags dstStage, + vk::DependencyFlags deps, + std::vector const& memoryBarriers, + std::vector const& bufferMemoryBarriers, + std::vector const& imageMemoryBarriers + ) const noexcept + { + vkCommandBuffer.pipelineBarrier( + srcStage, + dstStage, + deps, + memoryBarriers, + bufferMemoryBarriers, + imageMemoryBarriers + ); + } + + bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept + { + return cmdBufferState == SH_CMD_BUFFER_STATE::EXECUTABLE; + } + + void SHVkCommandBuffer::HandlePostSubmit(void) noexcept + { + SetState(SH_CMD_BUFFER_STATE::PENDING); + } + + //void SHVkCommandBuffer::PipelineBarrier(vk::PipelineStageFlags ) const noexcept + //{ + // //vkCommandBuffer.pipelineBarrier() + //} + + void SHVkCommandBuffer::ForceSetPipelineLayout(Handle pipelineLayout) noexcept + { + boundPipelineLayoutHdl = pipelineLayout; + } /***************************************************************************/ /*! - + \brief Calls vkCmdPushConstants and submits data stored in command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept @@ -502,13 +518,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Simply returns the command buffer handle. - - \return + + \return The command buffer handle. - + */ /***************************************************************************/ vk::CommandBuffer const& SHVkCommandBuffer::GetVkCommandBuffer(void) const noexcept @@ -518,11 +534,11 @@ namespace SHADE /***************************************************************************/ /*! - + \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. - + \param renderpassHdl Renderpass to get info from. @@ -532,9 +548,9 @@ namespace SHADE \param renderArea For the comparison. Again, look it up on the webpage. - \return + \return If optimal, true. otherwise false. - + */ /***************************************************************************/ bool SHVkCommandBuffer::IsRenderAreaOptimal(Handle const& renderpassHdl, vk::Extent2D const& framebufferExtent, vk::Rect2D const& renderArea) const noexcept @@ -546,14 +562,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Setter for the state of the command buffer. - + \param state - - \return - + + \return + */ /***************************************************************************/ void SHVkCommandBuffer::SetState(SH_CMD_BUFFER_STATE state) noexcept @@ -563,12 +579,12 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Returns the state of the command buffer. - - \return - + + \return + */ /***************************************************************************/ SH_CMD_BUFFER_STATE SHVkCommandBuffer::GetState(void) const noexcept @@ -578,14 +594,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Creates a command buffer. Cmd buffer can be primary or secondary. If secondary, flags will automatically have renderpass continue bit. Command 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. - + \param logicalDevice Need a logical device to create a buffer. @@ -594,7 +610,7 @@ namespace SHADE \param type Type of the command buffer; primary or secondary. - + */ /***************************************************************************/ SHVkCommandBuffer::SHVkCommandBuffer(Handle const& commandPool, SH_CMD_BUFFER_TYPE type) noexcept @@ -604,7 +620,7 @@ namespace SHADE , parentPoolResetMode{ SH_CMD_POOL_RESET::POOL_BASED } , usageFlags{} , commandBufferCount{ 0 } - , parentPool{commandPool} + , parentPool{ commandPool } , pushConstantData{} { @@ -645,54 +661,54 @@ namespace SHADE commandBufferType = type; commandBufferCount = allocateInfo.commandBufferCount; - if (parentPool->GetIsTransient ()) + if (parentPool->GetIsTransient()) usageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; if (commandBufferType == SH_CMD_BUFFER_TYPE::SECONDARY) usageFlags |= vk::CommandBufferUsageFlagBits::eRenderPassContinue; - + // Reset all the push constant data to 0 - memset (pushConstantData, 0, PUSH_CONSTANT_SIZE); + memset(pushConstantData, 0, PUSH_CONSTANT_SIZE); } /***************************************************************************/ /*! - + \brief Move ctor. Invalidates Vulkan handles. - + \param rhs the other command buffer. - + */ /***************************************************************************/ SHVkCommandBuffer::SHVkCommandBuffer(SHVkCommandBuffer&& rhs) noexcept - : vkCommandBuffer {std::move (rhs.vkCommandBuffer)} - , cmdBufferState {rhs.cmdBufferState} - , commandBufferType {rhs.commandBufferType} - , parentPoolResetMode {rhs.parentPoolResetMode} - , usageFlags {rhs.usageFlags} - , commandBufferCount {rhs.commandBufferCount} - , parentPool {rhs.parentPool} - , boundPipelineLayoutHdl{rhs.boundPipelineLayoutHdl } + : vkCommandBuffer{ std::move(rhs.vkCommandBuffer) } + , cmdBufferState{ rhs.cmdBufferState } + , commandBufferType{ rhs.commandBufferType } + , parentPoolResetMode{ rhs.parentPoolResetMode } + , usageFlags{ rhs.usageFlags } + , commandBufferCount{ rhs.commandBufferCount } + , parentPool{ rhs.parentPool } + , boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl } { - memcpy (pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); + memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); rhs.vkCommandBuffer = VK_NULL_HANDLE; } /***************************************************************************/ /*! - + \brief Move assignment operator. Invalidates Vulkan handles. - + \param rhs The other Vulkan Handle. - - \return + + \return a reference itself. - + */ /***************************************************************************/ SHVkCommandBuffer& SHVkCommandBuffer::operator=(SHVkCommandBuffer&& rhs) noexcept diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h index d945fce8..c18527b3 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h @@ -15,6 +15,7 @@ namespace SHADE class SHVkFramebuffer; class SHVkPipeline; class SHVkBuffer; + class SHVkImage; class SHVkDescriptorSetGroup; enum class SH_CMD_BUFFER_TYPE @@ -116,6 +117,10 @@ namespace SHADE // Draw Commands 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 DrawMultiIndirect (Handle indirectDrawData, uint32_t drawCount); + + // Buffer Copy + void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector& copyInfo); // memory barriers void PipelineBarrier ( @@ -129,7 +134,6 @@ namespace SHADE bool IsReadyToSubmit (void) const noexcept; void HandlePostSubmit (void) noexcept; - void DrawMultiIndirect (Handle indirectDrawData, uint32_t drawCount); // Push Constant variable setting template @@ -137,6 +141,7 @@ namespace SHADE { memcpy (static_cast(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T)); }; + void ForceSetPipelineLayout (Handle pipelineLayout) noexcept; void SubmitPushConstants (void) const noexcept; diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp index a1b1cbc2..6cd7ddfd 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp @@ -20,23 +20,6 @@ namespace SHADE } - /***************************************************************************/ - /*! - - \brief - Links the write infos to the vulkan write descriptor sets. - - */ - /***************************************************************************/ - void SHDescriptorSetUpdater::LinkInfoToWriteDescSet(void) noexcept - { - for (uint32_t i = 0; i < writeInfos.size(); ++i) - { - writeDescSets[i].pImageInfo = writeInfos[i].descImageInfos.data(); - writeDescSets[i].pBufferInfo = writeInfos[i].descBufferInfos.data(); - writeDescSets[i].pTexelBufferView = writeInfos[i].descTexelBufferInfos.data(); - } - } SHDescriptorWriteInfo& SHDescriptorWriteInfo::operator=(SHDescriptorWriteInfo&& rhs) noexcept { @@ -65,11 +48,6 @@ namespace SHADE } - std::vector const& SHDescriptorSetUpdater::GetWriteDescriptorSets(void) const noexcept - { - return writeDescSets; - } - SHDescriptorSetUpdater& SHDescriptorSetUpdater::operator=(SHDescriptorSetUpdater&& rhs) noexcept { if (&rhs == this) diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h index 7a5ae967..8595d2a0 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h @@ -41,10 +41,6 @@ namespace SHADE //! When we want to update a write, we need to use this to identify the index of the write. std::unordered_map writeHashMap; - //! We keep this here because we want this to be immediately passable to vkUpdateDescriptorSets - std::vector writeDescSets; - - void LinkInfoToWriteDescSet(void) noexcept; public: SHDescriptorSetUpdater (void) noexcept; @@ -52,8 +48,6 @@ namespace SHADE SHDescriptorSetUpdater& operator= (SHDescriptorSetUpdater&& rhs) noexcept; public: - std::vector const& GetWriteDescriptorSets (void) const noexcept; - friend class SHVkDescriptorSetGroup; }; } diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp index 77663ab8..6b770c3d 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp @@ -50,9 +50,8 @@ namespace SHADE return *this; } - std::vector> SHVkDescriptorPool::Allocate(const std::vector>& layouts, std::vector const& variableDescCounts) + Handle SHVkDescriptorPool::Allocate(const std::vector>& layouts, std::vector const& variableDescCounts) { - SHVkInstance::GetResourceManager().Create(device, GetHandle(), layouts, variableDescCounts); - return {}; + return SHVkInstance::GetResourceManager().Create(device, GetHandle(), layouts, variableDescCounts); } } diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h index 9314d940..91112496 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h @@ -39,7 +39,8 @@ namespace SHADE std::vector Limits = { { vk::DescriptorType::eCombinedImageSampler, 100 }, - { vk::DescriptorType::eUniformBuffer, 100 } + { vk::DescriptorType::eUniformBuffer, 100 }, + { vk::DescriptorType::eUniformBufferDynamic, 100 } }; /// /// Maximum number of descriptor sets allowed @@ -101,7 +102,7 @@ namespace SHADE /// Handles to the created Descriptor Sets. If this DescriptorPool has run out of /// space, lesser number of Handles will be returned. /// - std::vector> Allocate(const std::vector>& layouts, std::vector const& variableDescCounts); + Handle Allocate(const std::vector>& layouts, std::vector const& variableDescCounts); private: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp index 4e83d319..c1732535 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp @@ -7,6 +7,11 @@ #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Tools/SHLogger.h" +#include "Graphics/Images/SHVkImage.h" +#include "Graphics/Images/SHVkImageView.h" +#include "Graphics/Images/SHVkSampler.h" +#include "Graphics/Buffers/SHVkBuffer.h" +#include "Graphics/SHVkUtil.h" namespace SHADE { @@ -39,6 +44,7 @@ namespace SHADE : device{deviceHdl} , descPool {pool} , descSets{} + , layoutsUsed {layouts} { // Create the layout for each concurrent frame std::vector vkLayouts{ layouts.size() }; @@ -47,6 +53,7 @@ namespace SHADE for (uint32_t i = 0; i < layouts.size(); ++i) { vkLayouts[i] = layouts[i]->GetVkHandle(); + setIndexing.emplace(layouts[i]->GetSetIndex(), i); } // Check for variable descriptor count @@ -73,34 +80,22 @@ namespace SHADE // allocate descriptor sets descSets = device->GetVkLogicalDevice().allocateDescriptorSets(DESC_SET_LAYOUT_CREATE_INFO); - - - // Now we want to prepare the write descriptor sets for writing later. + // Now we want to prepare the write descriptor sets info for writing later. for (uint32_t i = 0; i < layouts.size(); ++i) { auto const& bindings = layouts[i]->GetBindings(); for (auto& binding : bindings) { BindingAndSetHash writeHash = binding.BindPoint; - writeHash |= static_cast(i) << 32; + writeHash |= static_cast(layouts[i]->GetSetIndex()) << 32; // new write for the binding updater.writeInfos.emplace_back(); updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1); auto& writeInfo = updater.writeInfos.back(); - updater.writeDescSets.emplace_back(); - auto& writeDescSet = updater.writeDescSets.back(); - - // Initialize info for write - writeDescSet.descriptorType = binding.Type; - writeDescSet.dstArrayElement = 0; - writeDescSet.dstSet = descSets[i]; - writeDescSet.dstBinding = binding.BindPoint; - // Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in uint32_t descriptorCount = (binding.flags & vk::DescriptorBindingFlagBits::eVariableDescriptorCount) ? variableDescCounts[i] : 1; - writeDescSet.descriptorCount = descriptorCount; switch (binding.Type) { @@ -114,8 +109,10 @@ namespace SHADE case vk::DescriptorType::eUniformTexelBuffer: case vk::DescriptorType::eStorageTexelBuffer: case vk::DescriptorType::eUniformBuffer: + case vk::DescriptorType::eUniformBufferDynamic: case vk::DescriptorType::eStorageBuffer: - writeInfo.descImageInfos.resize (descriptorCount); + case vk::DescriptorType::eStorageBufferDynamic: + writeInfo.descBufferInfos.resize (descriptorCount); break; //case vk::DescriptorType::eUniformBufferDynamic: // break; @@ -130,8 +127,6 @@ namespace SHADE } } } - // Link all the writeDescSet data for vkUpdateDescriptorSets to write to the linked descriptors - updater.LinkInfoToWriteDescSet(); } /***************************************************************************/ @@ -160,7 +155,7 @@ namespace SHADE */ /***************************************************************************/ - void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::vector> const& imageViewsAndSamplers) noexcept + void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span, Handle>> const& imageViewsAndSamplers) noexcept { // Find the target writeDescSet BindingAndSetHash writeHash = binding; @@ -176,32 +171,83 @@ namespace SHADE { // write sampler and image view auto& ivs = imageViewsAndSamplers[i]; - writeInfo.descImageInfos[i].imageView = ivs.first; - writeInfo.descImageInfos[i].sampler = ivs.second; + writeInfo.descImageInfos[i].imageView = ivs.first->GetImageView(); + writeInfo.descImageInfos[i].sampler = ivs.second->GetVkSampler(); } } - - void SHVkDescriptorSetGroup::UpdateDescriptorSet(void) noexcept + void SHVkDescriptorSetGroup::ModifyWriteDescBuffer(uint32_t set, uint32_t binding, std::span> const& buffers, uint32_t offset, uint32_t range) noexcept { - device->UpdateDescriptorSets(updater.GetWriteDescriptorSets()); + // Find the target writeDescSet + BindingAndSetHash writeHash = binding; + writeHash |= static_cast(set) << 32; + auto& writeInfo = updater.writeInfos[updater.writeHashMap.at(writeHash)]; + + if (buffers.size() > writeInfo.descBufferInfos.size()) + { + SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. "); + } + + for (uint32_t i = 0; i < buffers.size(); ++i) + { + // write sampler and image view + auto& buffer = buffers[i]; + writeInfo.descBufferInfos[i].buffer = buffer->GetVkBuffer(); + writeInfo.descBufferInfos[i].offset = offset; + writeInfo.descBufferInfos[i].range = range; + } + } - - void SHVkDescriptorSetGroup::UpdateSingleDescriptorSetImages(uint32_t set, uint32_t binding) noexcept + void SHVkDescriptorSetGroup::UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept { vk::WriteDescriptorSet writeDescSet{}; + // Get binding + set hash + BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding); + + // to index a set + uint32_t setIndex = setIndexing[bsHash]; + + // to index a write for a binding + uint32_t writeInfoIndex = updater.writeHashMap[bsHash]; + // Initialize info for write - writeDescSet.descriptorType = vk::DescriptorType::eCombinedImageSampler; + writeDescSet.descriptorType = layoutsUsed[setIndex]->GetBindings()[binding].Type; writeDescSet.dstArrayElement = 0; - writeDescSet.dstSet = descSets[set]; + writeDescSet.dstSet = descSets[setIndex]; writeDescSet.dstBinding = binding; - writeDescSet.pImageInfo = updater.writeInfos[set].descImageInfos.data(); - writeDescSet.descriptorCount = static_cast(updater.writeInfos[set].descImageInfos.size()); + writeDescSet.pImageInfo = updater.writeInfos[writeInfoIndex].descImageInfos.data(); + writeDescSet.descriptorCount = static_cast(updater.writeInfos[writeInfoIndex].descImageInfos.size()); device->UpdateDescriptorSet(writeDescSet); } + void SHVkDescriptorSetGroup::UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept + { + vk::WriteDescriptorSet writeDescSet{}; + + // Get binding + set hash + BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding); + + // to index a set + uint32_t setIndex = setIndexing[bsHash]; + + // to index a write for a binding + uint32_t writeInfoIndex = updater.writeHashMap[bsHash]; + + // Initialize info for write + writeDescSet.descriptorType = layoutsUsed[setIndex]->GetBindings()[binding].Type; + writeDescSet.dstArrayElement = 0; + writeDescSet.dstSet = descSets[setIndex]; + writeDescSet.dstBinding = binding; + + writeDescSet.pBufferInfo = updater.writeInfos[writeInfoIndex].descBufferInfos.data(); + writeDescSet.descriptorCount = static_cast(updater.writeInfos[writeInfoIndex].descBufferInfos.size()); + + device->UpdateDescriptorSet(writeDescSet); + + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h index b65fb1e6..d92d55e9 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h @@ -14,6 +14,10 @@ namespace SHADE class SHVkLogicalDevice; class SHVkDescriptorPool; class SHVkDescriptorSetLayout; + class SHVkSampler; + class SHVkImage; + class SHVkImageView; + class SHVkBuffer; /*---------------------------------------------------------------------------------*/ @@ -54,12 +58,14 @@ namespace SHADE SHVkDescriptorSetGroup& operator=(SHVkDescriptorSetGroup&& rhs) noexcept = default; /*-----------------------------------------------------------------------------*/ - /* Descriptor set writing */ + /* Public member functions */ /*-----------------------------------------------------------------------------*/ - void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::vector> const& imageViewsAndSamplers) noexcept; - void UpdateDescriptorSet(void) noexcept; + void UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept; + void UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept; + + void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span, Handle>> const& imageViewsAndSamplers) noexcept; + void ModifyWriteDescBuffer (uint32_t set, uint32_t binding, std::span> const& buffers, uint32_t offset, uint32_t range) noexcept; - void UpdateSingleDescriptorSetImages(uint32_t set, uint32_t binding) noexcept; /*-----------------------------------------------------------------------------*/ /* Getter Functions */ @@ -81,9 +87,17 @@ namespace SHADE //! Descriptor pool to allocate descriptor sets Handle descPool; + //! Sometimes when we pass in a layout, the set of the layout used in the + //! shader cannot be used to index into descSets. This is to mitigate that issue + //! when we update descriptor sets. + std::unordered_map setIndexing; + //! Descriptor sets std::vector descSets; + //! Layouts used to create this descriptor set group + std::vector> layoutsUsed; + //! for updating descriptor sets. We want to cache this so that we don't create the //! write structs at runtime. SHDescriptorSetUpdater updater; diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp index da1a3645..002aa29d 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp @@ -7,9 +7,10 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Constructor/Destructor */ /*---------------------------------------------------------------------------------*/ - SHVkDescriptorSetLayout::SHVkDescriptorSetLayout(Handle device, const std::vector& bindings) + SHVkDescriptorSetLayout::SHVkDescriptorSetLayout(Handle device, SetIndex set, const std::vector& bindings) : device { device } , layoutDesc { bindings } + , setIndex {set} { // Check if auto-binding point calculation configuration is valid bool autoCalc = false; @@ -74,6 +75,7 @@ namespace SHADE : device {rhs.device} , setLayout {rhs.setLayout} , layoutDesc{std::move (rhs.layoutDesc)} + , setIndex {rhs.setIndex} { rhs.setLayout = VK_NULL_HANDLE; } @@ -90,6 +92,11 @@ namespace SHADE return layoutDesc; } + SetIndex SHVkDescriptorSetLayout::GetSetIndex(void) const noexcept + { + return setIndex; + } + SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept { if (&rhs == this) @@ -98,6 +105,7 @@ namespace SHADE device = rhs.device; setLayout = rhs.setLayout; layoutDesc = std::move(rhs.layoutDesc); + setIndex = rhs.setIndex; rhs.setLayout = VK_NULL_HANDLE; diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h index 1acba189..9b436026 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h @@ -74,7 +74,7 @@ namespace SHADE /// /// /// - SHVkDescriptorSetLayout(Handle device, const std::vector& bindings); + SHVkDescriptorSetLayout(Handle device, SetIndex setIndex, const std::vector& bindings); SHVkDescriptorSetLayout(const SHVkDescriptorSetLayout&) = delete; SHVkDescriptorSetLayout(SHVkDescriptorSetLayout&& rhs) noexcept; /// @@ -97,6 +97,7 @@ namespace SHADE /// Handle to the Vulkan Descriptor Set Layout handle. inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; } std::vector const& GetBindings (void) const noexcept; + SetIndex GetSetIndex (void) const noexcept; private: /*-----------------------------------------------------------------------------*/ @@ -105,5 +106,6 @@ namespace SHADE Handle device; vk::DescriptorSetLayout setLayout; std::vector layoutDesc; // Stores description of the layout + SetIndex setIndex; // Index of the set }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp index a956af2c..5ed17511 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp @@ -467,7 +467,12 @@ namespace SHADE */ /***************************************************************************/ - Handle SHVkLogicalDevice::CreatePipelineLayout(SHPipelineLayoutParams& pipelineLayoutParams) noexcept + Handle SHVkLogicalDevice::CreatePipelineLayout(SHPipelineLayoutParams const& pipelineLayoutParams) noexcept + { + return SHVkInstance::GetResourceManager().Create (GetHandle(), pipelineLayoutParams); + } + + Handle SHVkLogicalDevice::CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy const& pipelineLayoutParams) noexcept { return SHVkInstance::GetResourceManager().Create (GetHandle(), pipelineLayoutParams); } @@ -488,9 +493,9 @@ namespace SHADE */ /***************************************************************************/ - Handle SHVkLogicalDevice::CreatePipeline(Handle const& pipelineLayoutHdl, SHVkPipelineState const* const state, Handle const& renderpassHdl, Handle subpass, SH_PIPELINE_TYPE type) noexcept + Handle SHVkLogicalDevice::CreateGraphicsPipeline(Handle const& pipelineLayoutHdl, SHVkPipelineState const* const state, Handle const& renderpassHdl, Handle subpass) noexcept { - return SHVkInstance::GetResourceManager().Create (GetHandle(), pipelineLayoutHdl, state, renderpassHdl, subpass, type); + return SHVkInstance::GetResourceManager().Create (GetHandle(), pipelineLayoutHdl, state, renderpassHdl, subpass); } @@ -510,9 +515,9 @@ namespace SHADE } - Handle SHVkLogicalDevice::CreateDescriptorSetLayout(std::vector const& bindings) noexcept + Handle SHVkLogicalDevice::CreateDescriptorSetLayout(SetIndex setIndex, std::vector const& bindings) noexcept { - return SHVkInstance::GetResourceManager().Create (GetHandle(), bindings); + return SHVkInstance::GetResourceManager().Create (GetHandle(), setIndex, bindings); } diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h index 6c59572a..8a197ef8 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h @@ -21,6 +21,7 @@ #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Graphics/Images/SHVkImage.h" + namespace SHADE { /*-----------------------------------------------------------------------*/ @@ -171,23 +172,23 @@ namespace SHADE std::string const& shaderName ) noexcept; - Handle CreatePipeline ( + Handle CreateGraphicsPipeline ( Handle const& pipelineLayoutHdl, SHVkPipelineState const* const state, Handle const& renderpassHdl, - Handle subpass, - SH_PIPELINE_TYPE type + Handle subpass ) noexcept; Handle CreateRenderpass (std::span const vkDescriptions, std::vector const& subpasses) noexcept; Handle CreateRenderpass (std::span const vkDescriptions, std::span const spDescs, std::span const spDeps) noexcept; Handle CreateFramebuffer (Handle const& renderpassHdl, std::vector> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept; - Handle CreateDescriptorSetLayout (std::vector const& bindings) noexcept; + Handle CreateDescriptorSetLayout (SetIndex setIndex, std::vector const& bindings) noexcept; Handle CreateDescriptorPools (const SHVkDescriptorPool::Config& config = {}) noexcept; Handle CreateDescriptorSetGroup(Handle pool, std::vector> const& layouts, std::vector const& variableDescCounts) noexcept; - Handle CreatePipelineLayout (SHPipelineLayoutParams& pipelineLayoutParams) noexcept; + Handle CreatePipelineLayout(SHPipelineLayoutParams const& pipelineLayoutParams) noexcept; + Handle CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy const& pipelineLayoutParams) noexcept; Handle CreateFence (void) const noexcept; Handle CreateSemaphore (void) const noexcept; diff --git a/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp b/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp index 6ec1c9f2..b8bf273e 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp +++ b/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp @@ -234,7 +234,7 @@ namespace SHADE return SHVkInstance::GetResourceManager().Create(inLogicalDeviceHdl, parent, createParams); } - void SHVkImage::TransferToDeviceResource(void) noexcept + void SHVkImage::TransferToDeviceResource(Handle cmdBufferHdl) noexcept { // prepare copy regions std::vector copyRegions{mipOffsets.size()}; @@ -252,7 +252,7 @@ namespace SHADE copyRegions[i].imageExtent = vk::Extent3D{ width >> i, height >> i, 1 }; } - //PrepareImageTransition(); + cmdBufferHdl->CopyBufferToImage(stagingBuffer, vkImage, copyRegions); } /***************************************************************************/ @@ -274,7 +274,7 @@ namespace SHADE */ /***************************************************************************/ - void SHVkImage::PrepareImageTransition(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept + void SHVkImage::PrepareImageTransitionInfo(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept { barrier.oldLayout = oldLayout; barrier.newLayout = newLayout; @@ -286,33 +286,6 @@ namespace SHADE barrier.subresourceRange.levelCount = mipLevelCount; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.layerCount = layerCount; - - vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe; - vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe; - - if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal) - { - srcStage = vk::PipelineStageFlagBits::eTopOfPipe; - dstStage = vk::PipelineStageFlagBits::eTransfer; - - barrier.srcAccessMask = vk::AccessFlagBits::eNone; - barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite; - } - else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) - { - srcStage = vk::PipelineStageFlagBits::eTransfer; - - // TODO, what if we want to access in compute shader - dstStage = vk::PipelineStageFlagBits::eFragmentShader; - - barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; - barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; - } - else - { - SHLOG_ERROR("Image layouts are invalid. "); - } - } void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept diff --git a/SHADE_Engine/src/Graphics/Images/SHVkImage.h b/SHADE_Engine/src/Graphics/Images/SHVkImage.h index eec8dc7e..91d4f2d2 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkImage.h +++ b/SHADE_Engine/src/Graphics/Images/SHVkImage.h @@ -135,8 +135,8 @@ namespace SHADE /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ Handle CreateImageView (Handle const& inLogicalDeviceHdl, Handle const& parent, SHImageViewDetails const& createParams) const noexcept; - void TransferToDeviceResource (void) noexcept; - void PrepareImageTransition (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept; + void TransferToDeviceResource (Handle cmdBufferHdl) noexcept; + void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept; /*-----------------------------------------------------------------------*/ /* GETTERS AND SETTERS */ diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp index e7a97126..b4bbf89b 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp +++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp @@ -4,4 +4,9 @@ namespace SHADE { + vk::Sampler SHVkSampler::GetVkSampler(void) const noexcept + { + return vkSampler; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.h b/SHADE_Engine/src/Graphics/Images/SHVkSampler.h index d58edb8f..eae23adf 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkSampler.h +++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.h @@ -22,6 +22,7 @@ namespace SHADE SHVkSampler (SHVkSampler&& rhs) noexcept; SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept; + vk::Sampler GetVkSampler (void) const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 08ffa88e..f73c5306 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -22,6 +22,8 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/Pipeline/SHVkPipeline.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" +#include "ECS_Base/Managers/SHComponentManager.h" +#include "Math/Transform/SHTransformComponent.h" namespace SHADE { @@ -33,6 +35,9 @@ namespace SHADE { if (!pipeline) throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!"); + + // Mark all as dirty + setAllDirtyFlags(); } void SHBatch::Add(const SHRenderable* renderable) @@ -52,6 +57,12 @@ namespace SHADE // Add renderable in subBatch->Renderables.insert(renderable); + + // Also add material instance in + referencedMatInstances.insert(renderable->GetMaterial()); + + // Mark all as dirty + setAllDirtyFlags(); } void SHBatch::Remove(const SHRenderable* renderable) @@ -59,14 +70,34 @@ namespace SHADE // Check if we have a SubBatch with the same mesh yet auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch) { - return batch.Mesh == renderable->Mesh; - }); + return batch.Mesh == renderable->Mesh; + }); // Attempt to remove if it exists if (subBatch == subBatches.end()) return; 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 + for (bool& dirt : isDirty) + dirt = true; } void SHBatch::Clear() @@ -81,15 +112,111 @@ namespace SHADE // Clear GPU buffers - drawDataBuffer.Free(); - transformDataBuffer.Free(); - matPropsBuffer.Free(); + for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) + { + drawDataBuffer[i].Free(); + transformDataBuffer[i].Free(); + matPropsBuffer[i].Free(); + } } - void SHBatch::Build(Handle device) + 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(matPropsDataSize), + vk::BufferUsageFlagBits::eStorageBuffer + ); + + // This frame is updated + matBufferDirty[frameIndex] = false; + } + + void SHBatch::UpdateTransformBuffer(uint32_t frameIndex) { + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + { + SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index."); + return; + } + + // Reset Transform Data + transformData.clear(); + + // Populate on the CPU + for (auto& subBatch : subBatches) + for (const SHRenderable* renderable : subBatch.Renderables) + { + // Transform + auto transform = SHComponentManager::GetComponent(renderable->GetEID()); + if (!transform) + { + SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); + transformData.emplace_back(); + } + else + { + transformData.emplace_back(transform->GetTRS()); + } + } + + // Transfer to GPU + if (transformDataBuffer[frameIndex]) + transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast(transformData.size() * sizeof(SHMatrix)), 0, 0); + } + + void SHBatch::Build(Handle _device, uint32_t frameIndex) + { + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + { + SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index."); + return; + } + // No need to build as there are no changes - if (!isDirty) + if (!isDirty[frameIndex]) return; // Count number of elements @@ -99,108 +226,133 @@ namespace SHADE numTotalElements += subBatch.Renderables.size(); } - // Generate CPU buffers - // - Draw data - drawData.reserve(subBatches.size()); - drawData.clear(); - // - Transform data - transformData.reserve(numTotalElements); - transformData.clear(); - // - Material Properties Data - const Handle SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface - ( - SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, - SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, - vk::ShaderStageFlagBits::eFragment - ); - const bool EMPTY_MAT_PROPS = !SHADER_INFO; - Byte singleMatPropSize = 0; - Byte matPropTotalBytes = 0; - if (!EMPTY_MAT_PROPS) + // Generate CPU buffers if there are changes + if (isCPUBuffersDirty) { - singleMatPropSize = SHADER_INFO->GetBytesRequired(); - matPropTotalBytes = drawData.size() * singleMatPropSize; - if (matPropsDataSize < matPropTotalBytes) + // - Draw data + drawData.reserve(subBatches.size()); + drawData.clear(); + // - Transform data + transformData.reserve(numTotalElements); + transformData.clear(); + // - Material Properties Data + const Handle SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface + ( + SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, + SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, + vk::ShaderStageFlagBits::eFragment + ); + const bool EMPTY_MAT_PROPS = !SHADER_INFO; + Byte matPropTotalBytes = 0; + if (!EMPTY_MAT_PROPS) { - matPropsData.reset(new char[matPropTotalBytes]); - matPropsDataSize = matPropTotalBytes; - } - } - - // Build Sub Batches - uint32_t nextInstanceIndex = 0; - char* propsCurrPtr = matPropsData.get(); - for (auto& subBatch : subBatches) - { - // Create command - drawData.emplace_back(vk::DrawIndexedIndirectCommand - { - .indexCount = subBatch.Mesh->IndexCount, - .instanceCount = static_cast(subBatch.Renderables.size()), - .firstIndex = subBatch.Mesh->FirstIndex, - .vertexOffset = subBatch.Mesh->FirstVertex, - .firstInstance = nextInstanceIndex - }); - - // Fill in buffers (CPU) - for (const SHRenderable* renderable : subBatch.Renderables) - { - // Transform - transformData.emplace_back(renderable->TransformMatrix); - // Material Properties - if (!EMPTY_MAT_PROPS) + singleMatPropSize = SHADER_INFO->GetBytesRequired(); + matPropTotalBytes = drawData.size() * singleMatPropSize; + if (matPropsDataSize < matPropTotalBytes) { - renderable->GetMaterial()->ExportProperties(propsCurrPtr); - propsCurrPtr += singleMatPropSize; + matPropsData.reset(new char[matPropTotalBytes]); + matPropsDataSize = matPropTotalBytes; } } + + // Build Sub Batches + uint32_t nextInstanceIndex = 0; + char* propsCurrPtr = matPropsData.get(); + for (auto& subBatch : subBatches) + { + // Create command + drawData.emplace_back(vk::DrawIndexedIndirectCommand + { + .indexCount = subBatch.Mesh->IndexCount, + .instanceCount = static_cast(subBatch.Renderables.size()), + .firstIndex = subBatch.Mesh->FirstIndex, + .vertexOffset = subBatch.Mesh->FirstVertex, + .firstInstance = nextInstanceIndex + }); + + // Fill in buffers (CPU) + for (const SHRenderable* renderable : subBatch.Renderables) + { + // Transform + auto transform = SHComponentManager::GetComponent_s(renderable->GetEID()); + if (!transform) + { + SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); + transformData.emplace_back(); + } + else + { + transformData.emplace_back(transform->GetTRS()); + } + + // Material Properties + if (!EMPTY_MAT_PROPS) + { + renderable->GetMaterial()->ExportProperties(propsCurrPtr); + propsCurrPtr += singleMatPropSize; + } + } + } + + // Successfully update CPU buffers + isCPUBuffersDirty = false; } // Send all buffered data to the GPU buffers using BuffUsage = vk::BufferUsageFlagBits; // - Draw Data - if (drawDataBuffer) - drawDataBuffer->Unmap(); const uint32_t DRAW_DATA_BYTES = static_cast(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand)); SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, drawDataBuffer, drawData.data(), DRAW_DATA_BYTES, + _device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES, BuffUsage::eIndirectBuffer ); - drawDataBuffer->Map(); // - Transform Buffer - if (transformDataBuffer) - transformDataBuffer->Unmap(); const uint32_t TF_DATA_BYTES = static_cast(transformData.size() * sizeof(SHMatrix)); SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, transformDataBuffer, transformData.data(), TF_DATA_BYTES, + _device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, BuffUsage::eVertexBuffer ); - transformDataBuffer->Map(); // - Material Properties Buffer - if (!EMPTY_MAT_PROPS) + if (matPropsData) { - if (matPropsBuffer) - matPropsBuffer->Unmap(); SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, matPropsBuffer, matPropsData.get(), static_cast(matPropTotalBytes), + _device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast(matPropsDataSize), BuffUsage::eStorageBuffer ); - matPropsBuffer->Map(); } - isDirty = false; + isDirty[frameIndex] = false; + + // Save logical device + this->device = _device; } /*---------------------------------------------------------------------------------*/ /* SHBatch - Usage Functions */ /*---------------------------------------------------------------------------------*/ - void SHBatch::Draw(Handle cmdBuffer) + void SHBatch::Draw(Handle cmdBuffer, uint32_t frameIndex) { + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + { + SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index."); + return; + } + cmdBuffer->BindPipeline(pipeline); - cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer, 0); - cmdBuffer->DrawMultiIndirect(drawDataBuffer, static_cast(drawData.size())); + cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); + cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast(drawData.size())); + } + + /*---------------------------------------------------------------------------------*/ + /* SHBatch - Helper Functions */ + /*---------------------------------------------------------------------------------*/ + void SHBatch::setAllDirtyFlags() + { + for (bool& dirt : isDirty) + dirt = true; + isCPUBuffersDirty = true; } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index a5b808ff..d40a66ea 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -14,12 +14,14 @@ of DigiPen Institute of Technology is prohibited. // STL Includes #include +#include // External Dependencies #include "Graphics/SHVulkanIncludes.h" // Project Includes #include "Resource/Handle.h" #include "Graphics/MiddleEnd/Interface/SHMaterial.h" #include "Math/SHMatrix.h" +#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" namespace SHADE { @@ -32,6 +34,7 @@ namespace SHADE class SHMesh; class SHRenderable; class SHVkLogicalDevice; + class SHMaterialInstance; /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -71,8 +74,10 @@ namespace SHADE void Add(const SHRenderable* renderable); void Remove(const SHRenderable* renderable); void Clear(); - void Build(Handle device); - void Draw(Handle cmdBuffer); + void UpdateMaterialBuffer(uint32_t frameIndex); + void UpdateTransformBuffer(uint32_t frameIndex); + void Build(Handle device, uint32_t frameIndex); + void Draw(Handle cmdBuffer, uint32_t frameIndex); /*-----------------------------------------------------------------------------*/ /* Getter Functions */ @@ -83,19 +88,30 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Data Members */ /*-----------------------------------------------------------------------------*/ + // Resources + Handle device; // Batch Properties Handle pipeline; + std::unordered_set> referencedMatInstances; + std::array matBufferDirty; // Batch Tree std::vector subBatches; - bool isDirty = true; + std::array isDirty; // CPU Buffers std::vector drawData; std::vector transformData; std::unique_ptr matPropsData; Byte matPropsDataSize = 0; + Byte singleMatPropSize = 0; + bool isCPUBuffersDirty = true; // GPU Buffers - Handle drawDataBuffer; - Handle transformDataBuffer; - Handle matPropsBuffer; + std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer; + std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> transformDataBuffer; + std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> matPropsBuffer; + + /*-----------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------*/ + void setAllDirtyFlags(); }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp index c92d9585..c4320aac 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp @@ -91,12 +91,12 @@ namespace SHADE (*superBatch)->Remove(renderable); } - void SHBatcher::FinaliseBatches(Handle device) + void SHBatcher::FinaliseBatches(Handle device, uint32_t frameIndex) { // Build SuperBatches for (auto& batch : superBatches) { - batch->Build(device); + batch->Build(device, frameIndex); } } @@ -109,6 +109,14 @@ namespace SHADE superBatches.clear(); } + void SHBatcher::UpdateBuffers(uint32_t frameIndex) + { + for (auto& batch : superBatches) + { + batch->UpdateBuffers(frameIndex); + } + } + void SHBatcher::RegisterSuperBatch(Handle superBatch) { superBatches.emplace_back(superBatch); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h index 4c8ac811..985e8e16 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h @@ -51,8 +51,9 @@ namespace SHADE void PrepareBatches(); void AddToBatch(SHRenderable const* renderable); void RemoveFromBatch(SHRenderable const* renderable); - void FinaliseBatches(Handle device); + void FinaliseBatches(Handle device, uint32_t frameIndex); void ClearBatches(); + void UpdateBuffers(uint32_t frameIndex); void RegisterSuperBatch(Handle superBatch); void DeregisterSuperBatch(Handle superBatch); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp index 09d2a720..b0173399 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp @@ -78,21 +78,30 @@ namespace SHADE batches.clear(); } - void SHSuperBatch::Build(Handle device) noexcept + void SHSuperBatch::UpdateBuffers(uint32_t frameIndex) { - // Build all batches for (auto& batch : batches) { - batch.Build(device); + batch.UpdateMaterialBuffer(frameIndex); + batch.UpdateTransformBuffer(frameIndex); } } - void SHSuperBatch::Draw(Handle cmdBuffer) noexcept + void SHSuperBatch::Build(Handle device, uint32_t frameIndex) noexcept { // Build all batches for (auto& batch : batches) { - batch.Draw(cmdBuffer); + batch.Build(device, frameIndex); + } + } + + void SHSuperBatch::Draw(Handle cmdBuffer, uint32_t frameIndex) noexcept + { + // Build all batches + for (auto& batch : batches) + { + batch.Draw(cmdBuffer, frameIndex); } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h index b44dd349..a09fc64e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h @@ -54,9 +54,10 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ void Add(const SHRenderable* renderable) noexcept; void Remove(const SHRenderable* renderable) noexcept; - void Clear() noexcept; - void Build(Handle device) noexcept; - void Draw(Handle cmdBuffer) noexcept; + void Clear() noexcept; + void UpdateBuffers(uint32_t frameIndex); + void Build(Handle device, uint32_t frameIndex) noexcept; + void Draw(Handle cmdBuffer, uint32_t frameIndex) noexcept; /*-----------------------------------------------------------------------------*/ /* Getter Functions */ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp index 5289b635..ee6d0e8c 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp @@ -2,6 +2,7 @@ #include "SHGraphicsGlobalData.h" #include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Pipeline/SHPipelineState.h" +#include "Graphics/Pipeline/SHVkPipelineLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" namespace SHADE @@ -27,7 +28,7 @@ namespace SHADE }; // For global data (generic data and textures) - Handle staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ genericDataBinding, texturesBinding }); + Handle staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding }); SHVkDescriptorSetLayout::Binding lightBinding { @@ -38,7 +39,7 @@ namespace SHADE }; // For Dynamic global data (lights) - Handle dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ lightBinding }); + Handle dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, { lightBinding }); SHVkDescriptorSetLayout::Binding cameraDataBinding { @@ -49,7 +50,7 @@ namespace SHADE }; // For High frequency global data (camera) - Handle cameraDataGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ cameraDataBinding }); + Handle cameraDataGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, { cameraDataBinding }); SHVkDescriptorSetLayout::Binding materialDataBinding { @@ -60,12 +61,15 @@ namespace SHADE }; // For High frequency global data (camera) - Handle materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding }); + Handle materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, { materialDataBinding }); globalDescSetLayouts.push_back(staticGlobalLayout); globalDescSetLayouts.push_back(dynamicGlobalLayout); globalDescSetLayouts.push_back(cameraDataGlobalLayout); globalDescSetLayouts.push_back(materialDataPerInstanceLayout); + + + dummyPipelineLayout = logicalDevice->CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy{globalDescSetLayouts}); } void SHGraphicsGlobalData::InitDefaultVertexInputState(void) noexcept @@ -94,4 +98,9 @@ namespace SHADE return defaultVertexInputState; } + Handle SHGraphicsGlobalData::GetDummyPipelineLayout(void) const noexcept + { + return dummyPipelineLayout; + } + } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h index fb595250..9333d0ab 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h @@ -9,6 +9,7 @@ namespace SHADE class SHVkLogicalDevice; class SHVkDescriptorSetLayout; class SHVkDescriptorSetGroup; + class SHVkPipelineLayout; class SH_API SHGraphicsGlobalData { @@ -22,6 +23,10 @@ namespace SHADE //! Default vertex input state (used by everything). SHVertexInputState defaultVertexInputState; + //! Since we want to bind global data but can't do so without a pipeline layout, + //! we create a dummy pipeline layout to use it for binding. + Handle dummyPipelineLayout; + void InitDescSetLayouts (Handle logicalDevice) noexcept; void InitDefaultVertexInputState(void) noexcept; public: @@ -35,5 +40,6 @@ namespace SHADE /*-----------------------------------------------------------------------*/ std::vector> const& GetDescSetLayouts (void) const noexcept; SHVertexInputState const& GetDefaultViState (void) const noexcept; + Handle GetDummyPipelineLayout (void) const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHCamera.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHCamera.cpp index 7e7412b9..4a1117c3 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHCamera.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHCamera.cpp @@ -22,24 +22,24 @@ namespace SHADE void SHCamera::SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up) { SHVec3 view = target - pos; view = SHVec3::Normalise(view); - SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right); - const SHVec3 UP = SHVec3::Cross(right, view); - - viewMatrix = SHMatrix::Identity; - viewMatrix(0, 0) = right[0]; - viewMatrix(1, 0) = right[1]; - viewMatrix(2, 0) = right[2]; - viewMatrix(0, 1) = UP[0]; - viewMatrix(1, 1) = UP[1]; - viewMatrix(2, 1) = UP[2]; - viewMatrix(0, 2) = -view[0]; - viewMatrix(1, 2) = -view[1]; - viewMatrix(2, 2) = -view[2]; - viewMatrix(3, 0) = -right.Dot(pos); - viewMatrix(3, 1) = -UP.Dot(pos); - viewMatrix(3, 2) = view.Dot(pos); - - isDirty = true; + SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right); + const SHVec3 UP = SHVec3::Cross(right, view); + + viewMatrix = SHMatrix::Identity; + viewMatrix(0, 0) = UP[0]; + viewMatrix(1, 0) = UP[1]; + viewMatrix(2, 0) = UP[2]; + viewMatrix(0, 1) = right[0]; + viewMatrix(1, 1) = right[1]; + viewMatrix(2, 1) = right[2]; + viewMatrix(0, 2) = view[0]; + viewMatrix(1, 2) = view[1]; + viewMatrix(2, 2) = view[2]; + viewMatrix(3, 0) = -UP.Dot(pos); + viewMatrix(3, 1) = -right.Dot(pos); + viewMatrix(3, 2) = -view.Dot(pos); + + isDirty = true; } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 1130a02b..2637cb75 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -29,6 +29,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/Batching/SHSuperBatch.h" #include "SHGraphicsConstants.h" #include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" +#include "Graphics/Buffers/SHVkBuffer.h" namespace SHADE { @@ -113,7 +114,8 @@ namespace SHADE screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f)); screenCamera->SetOrthographic(static_cast(windowDims.first), static_cast(windowDims.second), 0.01f, 100.0f); worldCamera = resourceManager.Create(); - worldCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f)); + //worldCamera->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f)); + worldCamera->SetLookAt(SHVec3(0.0f, 5.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f)); worldCamera->SetPerspective(90.0f, static_cast(windowDims.first), static_cast(windowDims.second), 0.0f, 100.0f); // Create Default Viewport @@ -129,7 +131,7 @@ namespace SHADE } // Initialize world render graph - worldRenderGraph->Init(device, swapchain, renderContextCmdPools, globalData); + worldRenderGraph->Init(device, swapchain, globalData); //worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); //worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); //worldRenderGraph->AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); @@ -148,9 +150,9 @@ namespace SHADE //compositeSubpass->AddInput("Position"); // TODO: Use macro to add this node when SH_EDITOR is enabled - //auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); - //auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); - //imguiSubpass->AddColorOutput("Present"); + auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"}); + auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); + imguiSubpass->AddColorOutput("Present"); worldRenderGraph->Generate(); @@ -167,7 +169,7 @@ namespace SHADE debugWorldRenderer->SetCamera(worldCamera);*/ // Add world renderer to default viewport - worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), descPool, globalData->GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph); + worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, globalData->GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph); worldRenderer->SetCamera(worldCamera); @@ -203,6 +205,7 @@ namespace SHADE { // Frame data for the current frame auto const& frameData = renderContext.GetCurrentFrameData(); + uint32_t frameIndex = renderContext.GetCurrentFrame(); // semaphore index. This is for render graphs to have semaphores to signal that the next render graph will use to wait on. bool semIndex = 0; @@ -219,7 +222,6 @@ namespace SHADE renderContext.ResetFence(); - // For every viewport for (int vpIndex = 0; vpIndex < static_cast(viewports.size()); ++vpIndex) { @@ -228,16 +230,42 @@ namespace SHADE // For every renderer for (int renIndex = 0; renIndex < static_cast(renderers.size()); ++renIndex) { - // Draw first - renderers[renIndex]->Draw(renderContext.GetCurrentFrame(), MESH_DATA); + /*-----------------------------------------------------------------------*/ + /* Renderer start */ + /*-----------------------------------------------------------------------*/ + // get command buffer of the renderer in the current frame + auto currentCmdBuffer = renderers[renIndex]->GetCommandBuffer(frameIndex); - // get render graph - auto rg = renderers[renIndex]->GetRenderGraph(); + // Begin recording the command buffer + currentCmdBuffer->BeginRecording(); + + currentCmdBuffer->ForceSetPipelineLayout(globalData->GetDummyPipelineLayout()); + + // Bind all the buffers required for meshes + for (auto& [buffer, bindingPoint] : MESH_DATA) + { + if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer) + currentCmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0); + else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer) + currentCmdBuffer->BindIndexBuffer(buffer, 0); + } + + // bind camera data + renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); + + // Draw first + renderers[renIndex]->Draw(frameIndex); + + // End the command buffer recording + currentCmdBuffer->EndRecording(); + /*-----------------------------------------------------------------------*/ + /* Renderer end */ + /*-----------------------------------------------------------------------*/ // submit a command buffer from the current render graph and make it wait for the previous render graph before submitting it to GPU. graphicsQueue->SubmitCommandBuffer ( - { rg->GetCommandBuffer(renderContext.GetCurrentFrame()) }, + { currentCmdBuffer }, { (vpIndex == viewports.size() - 1 && renIndex == renderers.size() - 1) ? frameData.semRenderFinishHdl : graphSemaphores[!semIndex] }, { (vpIndex == 0 && renIndex == 0) ? frameData.semImgAvailableHdl : graphSemaphores[semIndex] }, { vk::PipelineStageFlagBits::eColorAttachmentOutput }, @@ -279,7 +307,7 @@ namespace SHADE for (auto vp : viewports) for (auto renderer : vp->GetRenderers()) { - renderer->GetRenderGraph()->FinaliseBatch(); + renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame()); } // Resize @@ -387,14 +415,19 @@ namespace SHADE resourceManager.Free(material); } - Handle SHGraphicsSystem::AddMaterialInstance(Handle material) + Handle SHGraphicsSystem::AddOrGetBaseMaterialInstance(Handle material) { - return resourceManager.Create(material); + return materialInstanceCache.CreateOrGet(resourceManager, material); } - SHADE::Handle SHGraphicsSystem::AddMaterialInstance() + SHADE::Handle SHGraphicsSystem::AddOrGetBaseMaterialInstance() { - return AddMaterialInstance(defaultMaterial); + return AddOrGetBaseMaterialInstance(defaultMaterial); + } + + SHADE::Handle SHGraphicsSystem::AddMaterialInstanceCopy(Handle materialInst) + { + return resourceManager.Create(materialInst->GetBaseMaterial()); } void SHGraphicsSystem::RemoveMaterialInstance(Handle materialInstance) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 3dc452be..bee7a0f1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -28,6 +28,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h" #include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h" #include "SHMeshLibrary.h" +#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h" namespace SHADE { @@ -119,9 +120,10 @@ namespace SHADE /* Material Creation Functions */ /*-----------------------------------------------------------------------------*/ Handle AddMaterial(Handle vertShader, Handle fragShader, Handle subpass); - void RemoveMaterial(Handle material);; - Handle AddMaterialInstance(); - Handle AddMaterialInstance(Handle material); + void RemoveMaterial(Handle material); + Handle AddOrGetBaseMaterialInstance(); + Handle AddOrGetBaseMaterialInstance(Handle material); + Handle AddMaterialInstanceCopy(Handle materialInst); void RemoveMaterialInstance(Handle materialInstance); /*-----------------------------------------------------------------------------*/ @@ -228,8 +230,9 @@ namespace SHADE Handle globalData; // Middle End Resources - ResourceManager resourceManager; + ResourceManager resourceManager; SHMeshLibrary meshLibrary; + SHMaterialInstanceCache materialInstanceCache; // Viewports Handle defaultViewport; // Whole screen std::vector> viewports; // Additional viewports diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp index 57a91941..0e5a61dd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp @@ -38,7 +38,7 @@ namespace SHADE dataStore.reset(); } - void SHMaterialInstance::ExportProperties(void* dest) const + void SHMaterialInstance::ExportProperties(void* dest) { assert(dataStore != nullptr); @@ -62,6 +62,9 @@ namespace SHADE const auto DATA_OFFSET = variable->offset; memcpy(static_cast(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize); } + + // Data was exported so unflag + dataWasChanged = false; } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h index db0201b7..5d6c4925 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h @@ -62,12 +62,13 @@ namespace SHADE template const T& GetProperty(const std::string& key) const; void ResetProperties() noexcept; - void ExportProperties(void* dest) const; + void ExportProperties(void* dest); /*-----------------------------------------------------------------------------*/ /* Getter Functions */ /*-----------------------------------------------------------------------------*/ - Handle GetBaseMaterial() const { return baseMaterial; } + Handle GetBaseMaterial() const noexcept { return baseMaterial; } + bool HasChanged() const noexcept { return dataWasChanged; } private: /*-----------------------------------------------------------------------------*/ @@ -77,6 +78,7 @@ namespace SHADE std::vector overrideData; std::unique_ptr dataStore; size_t dataStoreSize = 0; + bool dataWasChanged = false; /*-----------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp index 0aead306..b3dc6c3a 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp @@ -53,6 +53,9 @@ namespace SHADE // Save the override data information overrideData.emplace_back(std::move(od)); + + // Flag + dataWasChanged = true; } template T& SHMaterialInstance::GetProperty(const std::string& key) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 984e753b..a4cda42d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -27,7 +27,6 @@ namespace SHADE sharedMaterial = {}; material = {}; oldMaterial = {}; - } void SHRenderable::OnDestroy() @@ -82,7 +81,7 @@ namespace SHADE if (!material) { SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem(); - material = gfxSystem->AddMaterialInstance(sharedMaterial->GetBaseMaterial()); + material = gfxSystem->AddOrGetBaseMaterialInstance(sharedMaterial->GetBaseMaterial()); } return material; @@ -93,5 +92,4 @@ namespace SHADE materialChanged = false; oldMaterial = {}; } - } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index 0d48b5cb..3bb7cfda 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -66,7 +66,6 @@ namespace SHADE /* Data Members */ /*-------------------------------------------------------------------------------*/ Handle Mesh; - SHMatrix TransformMatrix; // TODO: Replace with Transform component private: /*-------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp index 90e137fe..c7e2a86d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp @@ -20,20 +20,33 @@ of DigiPen Institute of Technology is prohibited. #include "SHMaterial.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" +#include "Graphics/Buffers/SHVkBuffer.h" namespace SHADE { /*-----------------------------------------------------------------------------------*/ /* Constructor/Destructors */ /*-----------------------------------------------------------------------------------*/ - SHRenderer::SHRenderer(Handle logicalDevice, uint32_t numFrames, Handle descriptorPool, Handle cameraDescLayout, Handle viewport, Handle renderGraph) + SHRenderer::SHRenderer(Handle logicalDevice, uint32_t numFrames, std::vector>& cmdPools, Handle descriptorPool, Handle cameraDescLayout, Handle viewport, Handle renderGraph) : viewport { viewport } , renderGraph { renderGraph } { - cameraDescriptorSet = logicalDevice->CreateDescriptorSetGroup(descriptorPool, { cameraDescLayout }, { 1 }); - cpuCameraData.resize(numFrames); + commandBuffers.resize(static_cast(numFrames)); + + for (uint32_t i = 0; i < commandBuffers.size(); ++i) + commandBuffers[i] = cmdPools[i]->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); + + cameraDescriptorSet = descriptorPool->Allocate({ cameraDescLayout }, { 1 }); cameraDataAlignedSize = logicalDevice->PadUBOSize(sizeof(SHShaderCameraData)); + + cameraBuffer = logicalDevice->CreateBuffer(cameraDataAlignedSize * numFrames, nullptr, cameraDataAlignedSize * numFrames, vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + + std::array cameraBufferArray{cameraBuffer}; + + cameraDescriptorSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA, std::span>{ cameraBufferArray.data(), cameraBufferArray.size()}, 0, sizeof (SHShaderCameraData)); + + cameraDescriptorSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA); } /*-----------------------------------------------------------------------------------*/ @@ -47,21 +60,33 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Drawing Functions */ /*-----------------------------------------------------------------------------------*/ - void SHRenderer::Draw(uint32_t frameIndex, std::initializer_list, uint32_t>> graphScopeBuffers) noexcept + void SHRenderer::Draw(uint32_t frameIndex) noexcept { - renderGraph->Execute(frameIndex, graphScopeBuffers); + renderGraph->Execute(frameIndex, commandBuffers[frameIndex]); } - void SHRenderer::BindDescriptorSet(Handle cmdBuffer, uint32_t frameIndex) noexcept + void SHRenderer::UpdateDataAndBind(Handle cmdBuffer, uint32_t frameIndex) noexcept { - std::array dynamicOffsets{ frameIndex * cameraDataAlignedSize }; + cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix(); + cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex); + + std::array dynamicOffsets{ frameIndex * cameraDataAlignedSize }; cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 }); } + void SHRenderer::UpdateCameraDataToBuffer(void) noexcept + { + } + Handle SHRenderer::GetRenderGraph(void) const noexcept { return renderGraph; } + Handle SHRenderer::GetCommandBuffer(uint32_t frameIndex) const noexcept + { + return commandBuffers[frameIndex]; + } + } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h index 843ad6bf..255ab289 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.h @@ -39,6 +39,7 @@ namespace SHADE class SHVkDescriptorSetGroup; class SHGraphicsGlobalData; class SHVkDescriptorPool; + class SHVkBuffer; struct SHShaderCameraData { @@ -63,7 +64,7 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Constructor/Destructors */ /*-----------------------------------------------------------------------------*/ - SHRenderer(Handle logicalDevice, uint32_t numFrames, Handle descriptorPool, Handle cameraDescLayout, Handle viewport, Handle renderGraph); + SHRenderer(Handle logicalDevice, uint32_t numFrames, std::vector>& cmdPools, Handle descriptorPool, Handle cameraDescLayout, Handle viewport, Handle renderGraph); /*-----------------------------------------------------------------------------*/ /* Camera Registration */ @@ -73,13 +74,15 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Drawing Functions */ /*-----------------------------------------------------------------------------*/ - void Draw(uint32_t frameIndex, std::initializer_list, uint32_t>> graphScopeBuffers) noexcept; - void BindDescriptorSet (Handle cmdBuffer, uint32_t frameIndex) noexcept; + void Draw(uint32_t frameIndex) noexcept; + void UpdateDataAndBind (Handle cmdBuffer, uint32_t frameIndex) noexcept; + void UpdateCameraDataToBuffer (void) noexcept; /*-----------------------------------------------------------------------------*/ /* Setters and Getters */ /*-----------------------------------------------------------------------------*/ Handle GetRenderGraph (void) const noexcept; + Handle GetCommandBuffer(uint32_t frameIndex) const noexcept; private: /*-----------------------------------------------------------------------------*/ @@ -92,7 +95,16 @@ namespace SHADE Handle camera; Handle renderGraph; Handle cameraDescriptorSet; - std::vector cpuCameraData; + Handle cameraBuffer; + + // we really only need 1 copy even though we need %swapchainImages copies for + // GPU. + SHShaderCameraData cpuCameraData; + + //! Command buffers for the render graph + std::vector> commandBuffers; + + }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp index 1e38acf1..25c5bca2 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.cpp @@ -49,10 +49,10 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Renderer Registration Functions */ /*---------------------------------------------------------------------------------*/ - Handle SHViewport::AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, Handle descriptorPool, Handle cameraDescLayout, Handle renderGraph) + Handle SHViewport::AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, std::vector>& cmdPools, Handle descriptorPool, Handle cameraDescLayout, Handle renderGraph) { // Create the renderer - auto renderer = resourceManager.Create(device, numFrames, descriptorPool, cameraDescLayout, GetHandle(), renderGraph); + auto renderer = resourceManager.Create(device, numFrames, cmdPools, descriptorPool, cameraDescLayout, GetHandle(), renderGraph); // Store renderers.emplace_back(renderer); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.h index 608446a3..d97d62ce 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHViewport.h @@ -32,6 +32,7 @@ namespace SHADE class SHRenderGraph; class SHVkDescriptorPool; class SHVkDescriptorSetLayout; + class SHVkCommandPool; /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -58,7 +59,7 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Renderers Registration Functions */ /*-----------------------------------------------------------------------------*/ - Handle AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, Handle descriptorPool, Handle cameraDescLayout, Handle renderGraph); + Handle AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, std::vector>& cmdPools, Handle descriptorPool, Handle cameraDescLayout, Handle renderGraph); void RemoveRenderer(Handle renderer); /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.cpp new file mode 100644 index 00000000..ed3d27c3 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.cpp @@ -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 SHMaterialInstanceCache::CreateOrGet(ResourceManager& manager, Handle 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(material)).first->second; + } + + return matInst->second; + } + + void SHMaterialInstanceCache::Remove(Handle material) + { + cache.erase(material); + } + + void SHMaterialInstanceCache::Clear() + { + cache.clear(); + } +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h b/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h new file mode 100644 index 00000000..d85cb553 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h @@ -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 +// 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 CreateOrGet(ResourceManager& manager, Handle 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 material); + /***********************************************************************************/ + /*! + + \brief + Removes all SHMaterialInstances in the cache. + + */ + /***********************************************************************************/ + void Clear(); + + private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + using MaterialMap = std::unordered_map, Handle>; + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + MaterialMap cache; + }; +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp index e09a4945..92d832f1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp @@ -18,7 +18,7 @@ namespace SHADE auto pipelineLayout = logicalDevice->CreatePipelineLayout(params); // Create the pipeline and configure the default vertex input state - auto newPipeline = logicalDevice->CreatePipeline(pipelineLayout, nullptr, renderpass, subpass, SH_PIPELINE_TYPE::GRAPHICS); + auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass); newPipeline->GetPipelineState().SetVertexInputState(globalData->GetDefaultViState()); // Actually construct the pipeline diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp new file mode 100644 index 00000000..6459ff9a --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp @@ -0,0 +1,142 @@ +/************************************************************************************//*! +\file SHTextureLibrary.cpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Sep 20, 2022 +\brief Contains definitions for all of the functions of the classes that deal + with storage and management of buffers for textures. + +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 "SHTextureLibrary.h" + +#include "Graphics/SHVulkanIncludes.h" + +#include "Graphics/Devices/SHVkLogicalDevice.h" +#include "Graphics/Buffers/SHVkBuffer.h" +#include "Graphics/Commands/SHVkCommandBuffer.h" +#include "Graphics/SHVkUtil.h" +#include "Tools/SHLogger.h" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + Handle SHTextureLibrary::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels) + { + isDirty = true; + + auto handle = resourceManager.Create(); + addJobs.emplace_back(AddJob { pixelCount, pixelData, format, mipLevels }); + return handle; + } + + void SHTextureLibrary::Remove(Handle texture) + { + if (!texture) + throw std::invalid_argument("Attempted to remove a Texture that did not belong to the Texture Library!"); + + removeJobs.emplace_back(texture); + isDirty = true; + } + + void SHTextureLibrary::BuildImages(Handle device, Handle cmdBuffer, Handle graphicsQueue, Handle descPool, Handle descLayout) + { + /* Remove Textures */ + std::vector pipelineBarriers(addJobs.size()); + + /* Add Textures */ + // Transition + for (int i = 0; auto& job : addJobs) + { + job.Image = resourceManager.Create(); + job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, pipelineBarriers[i]); + ++i; + } + vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe; + vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe; + preparePipelineBarriers(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, srcStage, dstStage, pipelineBarriers); + cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers); + + // Copy + for (auto& job : addJobs) + { + job.Image->TransferToDeviceResource(cmdBuffer); + } + + // Transition + for (int i = 0; auto & job : addJobs) + { + // Transition + job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, pipelineBarriers[i]); + } + preparePipelineBarriers(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, srcStage, dstStage, pipelineBarriers); + cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers); + + // Execute Commands + graphicsQueue->SubmitCommandBuffer({ cmdBuffer }); + device->WaitIdle(); + + // Create Image View + for (auto& job : addJobs) + { + const SHImageViewDetails DETAILS + { + .viewType = vk::ImageViewType::e2D, + .format = job.TextureFormat, + .imageAspectFlags = vk::ImageAspectFlagBits::eColor, + .baseMipLevel = 0, + .mipLevelCount = job.MipLevels, + .baseArrayLayer = 0, + .layerCount = 0 + }; + job.Handle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS); + } + + // Build Descriptor + Handle descSetGroup = descPool->Allocate({ descLayout }, { 1 }); + + + isDirty = false; + } + + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + void SHTextureLibrary::preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector& barriers) + { + if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal) + { + srcStage = vk::PipelineStageFlagBits::eTopOfPipe; + dstStage = vk::PipelineStageFlagBits::eTransfer; + + for (auto& barrier : barriers) + { + barrier.srcAccessMask = vk::AccessFlagBits::eNone; + barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite; + } + } + else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) + { + srcStage = vk::PipelineStageFlagBits::eTransfer; + + // TODO, what if we want to access in compute shader + dstStage = vk::PipelineStageFlagBits::eFragmentShader; + + for (auto& barrier : barriers) + { + barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; + barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; + } + } + else + { + SHLOG_ERROR("Image layouts are invalid. "); + } + } + +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h new file mode 100644 index 00000000..5cf974ef --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h @@ -0,0 +1,163 @@ +/************************************************************************************//*! +\file SHTextureLibrary.h +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Sep 20, 2022 +\brief Contains definitions for all of the classes that deal with storage and + management of textures. + +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 +// Project Includes +#include "Resource/Handle.h" +#include "Resource/ResourceLibrary.h" +#include "Math/SHMath.h" +#include "Graphics/SHVulkanIncludes.h" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*---------------------------------------------------------------------------------*/ + class SHVkBuffer; + class SHVkLogicalDevice; + class SHVkCommandBuffer; + class SHVkImage; + class SHVkImageView; + class SHVkQueue; + class SHVkDescriptorPool; + class SHVkDescriptorSetLayout; + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + class SHTexture + { + public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + using PixelChannel = float; + using TextureFormat = vk::Format; // TODO: Change + using Index = uint32_t; + + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + Handle ImageView; + Index TextureArrayIndex = std::numeric_limits::max(); + }; + /***********************************************************************************/ + /*! + \brief + Manages storage for all textures in the Graphics System as a single set of + textures. + */ + /***********************************************************************************/ + class SHTextureLibrary + { + public: + /*-----------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------*/ + /*******************************************************************************/ + /*! + + \brief + Adds a texture to the Texture Library. But this does not mean that the + textures have been added yet. A call to "BuildImages()" is required to + transfer all textures into the GPU. + + \param pixelCount + Number of pixels in this Mesh. + \param positions + Pointer to the first in a contiguous array of SHMathVec3s that define vertex + positions. + \param format + Format of the texture loaded in. + + \return + Handle to the created Texture. This is not valid to be used until a call to + BuildImages(). + + */ + /*******************************************************************************/ + Handle Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels); + /*******************************************************************************/ + /*! + + \brief + Removes a mesh from the Texture Library. But this does not mean that the + textures have been removed yet. A call to "BuildImages()" is required to + finalise all changes. + + \param mesh + Handle to the mesh to remove. + + */ + /*******************************************************************************/ + void Remove(Handle mesh); + /***************************************************************************/ + /*! + + \brief + Finalises all changes to the Texture Library into the GPU buffers. + + \param device + Device used to create and update the buffers. + \param cmdBuffer + Command buffer used to set up transfers of data in the GPU memory. This + call must be preceded by calls to cmdBuffer's BeginRecording() and ended + with EndRecording(). Do recall to also submit the cmdBuffer to a transfer + queue. + */ + /***************************************************************************/ + void BuildImages(Handle device, Handle cmdBuffer, Handle graphicsQueue, Handle descPool, Handle descLayout); + + /*-----------------------------------------------------------------------------*/ + /* Getter Functions */ + /*-----------------------------------------------------------------------------*/ + Handle GetTextureBuffer() const noexcept { return texStorageBuffer; } + + private: + /*-----------------------------------------------------------------------------*/ + /* Type Definition */ + /*-----------------------------------------------------------------------------*/ + struct AddJob + { + uint32_t PixelCount = 0; + const SHTexture::PixelChannel* PixelData = nullptr; + SHTexture::TextureFormat TextureFormat = {}; + uint32_t MipLevels = 0; + Handle Image; + Handle Handle; + }; + + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + // Manipulation Queues + std::vector addJobs; + std::vector> removeJobs; + // Tracking + ResourceManager resourceManager; + std::vector> texOrder; + // CPU Storage + std::vector texStorage; + // GPU Storage + Handle texStorageBuffer{}; + // Flags + bool isDirty = true; + + /*-----------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------*/ + void preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector& barriers); + }; +} diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineLayoutParams.h b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineLayoutParams.h index 493bd114..093e03d4 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineLayoutParams.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineLayoutParams.h @@ -25,6 +25,15 @@ namespace SHADE //! want to use it for allocating descriptor sets. std::vector> const& globalDescSetLayouts = {}; }; + + struct SHPipelineLayoutParamsDummy + { + /*-----------------------------------------------------------------------*/ + /* MEMBER VARIABLES */ + /*-----------------------------------------------------------------------*/ + + std::vector> const& globalDescSetLayouts = {}; + }; } #endif diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h index a43035f5..2769d6cc 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.h @@ -64,7 +64,7 @@ namespace SHADE vk::CullModeFlags cull_mode{ vk::CullModeFlagBits::eBack }; //! CW or CCW - vk::FrontFace frontFacingOrientation{ vk::FrontFace::eClockwise }; + vk::FrontFace frontFacingOrientation{ vk::FrontFace::eCounterClockwise }; bool depthBias{ VK_FALSE }; }; diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp index 1c47c21a..c03fd2a7 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp @@ -179,7 +179,7 @@ namespace SHADE /*! \brief - Non-default ctor. + Non-default ctor for creating graphics pipeline. \param inLogicalDeviceHdl Needed for creation and destruction. @@ -200,14 +200,12 @@ namespace SHADE The subpass that this pipeline will be used in. If state is not nullptr, this parameter is ignored. - \param type - The type of the pipeline. */ /***************************************************************************/ - SHVkPipeline::SHVkPipeline(Handle const& inLogicalDeviceHdl, Handle const& inPipelineLayout, SHVkPipelineState const* const state, Handle const& renderpassHdl, Handle subpass, SH_PIPELINE_TYPE type) noexcept + SHVkPipeline::SHVkPipeline(Handle const& inLogicalDeviceHdl, Handle const& inPipelineLayout, SHVkPipelineState const* const state, Handle const& renderpassHdl, Handle subpass) noexcept : pipelineState{ } - , pipelineType {type} + , pipelineType {SH_PIPELINE_TYPE::GRAPHICS} , vkPipeline {VK_NULL_HANDLE} , logicalDeviceHdl{ inLogicalDeviceHdl } , pipelineLayout { inPipelineLayout } @@ -250,6 +248,33 @@ namespace SHADE vkPipeline = VK_NULL_HANDLE; } + /***************************************************************************/ + /*! + + \brief + Just to differentiate between compute and graphics pipeline, we will + have a constructor that takes in less parameters; sufficient for the + compute pipeline to be created. + + \param inLogicalDeviceHdl + \param inPipelineLayout + + \return + + */ + /***************************************************************************/ + SHVkPipeline::SHVkPipeline(Handle const& inLogicalDeviceHdl, Handle const& inPipelineLayout) noexcept + : pipelineState{ } + , pipelineType{ SH_PIPELINE_TYPE::COMPUTE } + , vkPipeline{ VK_NULL_HANDLE } + , logicalDeviceHdl{ inLogicalDeviceHdl } + , pipelineLayout{ inPipelineLayout } + , created{ false } + + { + + } + /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h index 6edf0e98..fe55a41e 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h @@ -51,8 +51,10 @@ namespace SHADE Handle const& inPipelineLayout, SHVkPipelineState const* const state, Handle const& renderpassHdl, - Handle subpass, - SH_PIPELINE_TYPE type) noexcept; + Handle subpass) noexcept; + + SHVkPipeline(Handle const& inLogicalDeviceHdl, + Handle const& inPipelineLayout) noexcept; SHVkPipeline (SHVkPipeline&& rhs) noexcept; ~SHVkPipeline (void) noexcept; diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp index cc738aed..25be112e 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp @@ -198,7 +198,7 @@ namespace SHADE // 1 descriptor set layout for every descriptor set detected. for (auto const& set : setsWithBindings) { - auto newDescriptorSetLayout = logicalDeviceHdl->CreateDescriptorSetLayout(set.second); + auto newDescriptorSetLayout = logicalDeviceHdl->CreateDescriptorSetLayout(set.first, set.second); descriptorSetLayoutsAllocate.push_back(newDescriptorSetLayout); } @@ -254,12 +254,6 @@ namespace SHADE // Clear pc ranges vkPcRanges.clear(); - // Kill all descriptor set layouts - for (auto& layout : descriptorSetLayoutsGlobal) - SHVkInstance::GetResourceManager().Free(layout); - - descriptorSetLayoutsGlobal.clear(); - for (auto& layout : descriptorSetLayoutsAllocate) SHVkInstance::GetResourceManager().Free(layout); @@ -285,9 +279,9 @@ namespace SHADE */ /***************************************************************************/ - SHVkPipelineLayout::SHVkPipelineLayout(Handle const& inLogicalDeviceHdl, SHPipelineLayoutParams& pipelineLayoutParams) noexcept + SHVkPipelineLayout::SHVkPipelineLayout(Handle const& inLogicalDeviceHdl, SHPipelineLayoutParams const& pipelineLayoutParams) noexcept : vkPipelineLayout {VK_NULL_HANDLE} - , shaderModules{std::move (pipelineLayoutParams.shaderModules)} + , shaderModules{pipelineLayoutParams.shaderModules} , logicalDeviceHdl {inLogicalDeviceHdl} , pushConstantInterface{} , vkPcRanges{} @@ -308,6 +302,46 @@ namespace SHADE RecreateIfNeeded (); } + + SHVkPipelineLayout::SHVkPipelineLayout(Handle const& inLogicalDeviceHdl, SHPipelineLayoutParamsDummy const& pipelineLayoutParams) noexcept + : vkPipelineLayout{ VK_NULL_HANDLE } + , shaderModules{ } + , logicalDeviceHdl{ inLogicalDeviceHdl } + , pushConstantInterface{} + , vkPcRanges{} + , descriptorSetLayoutsGlobal{} + , descriptorSetLayoutsAllocate{} + , vkDescriptorSetLayoutsAllocate{} + , vkDescriptorSetLayoutsPipeline{} + + { + vkDescriptorSetLayoutsPipeline.resize(pipelineLayoutParams.globalDescSetLayouts.size()); + for (uint32_t i = 0; auto& layout : vkDescriptorSetLayoutsPipeline) + { + layout = pipelineLayoutParams.globalDescSetLayouts[i]->GetVkHandle(); + ++i; + } + + vk::PipelineLayoutCreateInfo plCreateInfo{}; + + // Set push constant data to pipeline layout + plCreateInfo.pushConstantRangeCount = 0; + plCreateInfo.pPushConstantRanges = nullptr; + + // To initialize the descriptor set layouts for the pipeline layout. + plCreateInfo.setLayoutCount = static_cast(vkDescriptorSetLayoutsPipeline.size()); + plCreateInfo.pSetLayouts = vkDescriptorSetLayoutsPipeline.data(); + + if (auto const RESULT = logicalDeviceHdl->GetVkLogicalDevice().createPipelineLayout(&plCreateInfo, nullptr, &vkPipelineLayout); RESULT != vk::Result::eSuccess) + { + SHVulkanDebugUtil::ReportVkError(RESULT, "Failed to create Pipeline Layout. "); + return; + } + else + SHVulkanDebugUtil::ReportVkSuccess("Successfully created Pipeline Layout. "); + + } + /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h index bce827a7..e43ceb73 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h @@ -57,7 +57,8 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ /*-----------------------------------------------------------------------*/ - SHVkPipelineLayout (Handle const& inLogicalDeviceHdl, SHPipelineLayoutParams& pipelineLayoutParams) noexcept; + SHVkPipelineLayout(Handle const& inLogicalDeviceHdl, SHPipelineLayoutParams const& pipelineLayoutParams) noexcept; + SHVkPipelineLayout(Handle const& inLogicalDeviceHdl, SHPipelineLayoutParamsDummy const& pipelineLayoutParams) noexcept; SHVkPipelineLayout (SHVkPipelineLayout&& rhs) noexcept; ~SHVkPipelineLayout (void) noexcept; SHVkPipelineLayout& operator= (SHVkPipelineLayout&& rhs) noexcept; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index d7404db2..3f5641c0 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -220,7 +220,6 @@ namespace SHADE , depthReferences{} , inputReferences{} { - superBatch = rm.Create(GetHandle()); } /***************************************************************************/ @@ -346,10 +345,13 @@ namespace SHADE inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal }); } - void SHSubpass::Execute(Handle& commandBuffer) noexcept + void SHSubpass::Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept { + // Ensure correct transforms are provided + superBatch->UpdateBuffers(frameIndex); + // Draw all the batches - superBatch->Draw(commandBuffer); + superBatch->Draw(commandBuffer, frameIndex); // Draw all the exterior draw calls for (auto& drawCall : exteriorDrawCalls) @@ -363,6 +365,12 @@ namespace SHADE exteriorDrawCalls.push_back(newDrawCall); } + void SHSubpass::Init(ResourceManager& resourceManager) noexcept + { + superBatch = resourceManager.Create(GetHandle()); + + } + /***************************************************************************/ /*! @@ -521,6 +529,9 @@ namespace SHADE , configured{ rhs.configured } , executed{ rhs.executed } , ptrToResources{ rhs.ptrToResources } + , pipelineLibrary{ std::move(rhs.pipelineLibrary) } + , batcher { std::move(rhs.batcher) } + { rhs.renderpass = {}; } @@ -541,6 +552,8 @@ namespace SHADE resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping); subpassIndexing = std::move(rhs.subpassIndexing); ptrToResources = std::move(rhs.ptrToResources); + pipelineLibrary = std::move(rhs.pipelineLibrary); + batcher = std::move(rhs.batcher); rhs.renderpass = {}; @@ -574,6 +587,7 @@ namespace SHADE subpasses.emplace_back(resourceManager.Create(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources)); subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); Handle subpass = subpasses.back(); + subpass->Init(resourceManager); // Register the SuperBatch batcher.RegisterSuperBatch(subpass->GetSuperBatch()); @@ -588,7 +602,7 @@ namespace SHADE for (uint32_t i = 0; i < subpasses.size(); ++i) { - subpasses[i]->Execute(commandBuffer); + subpasses[i]->Execute(commandBuffer, frameIndex); // Go to next subpass if not last subpass if (i != subpasses.size() - 1) @@ -621,9 +635,9 @@ namespace SHADE return pipeline; } - void SHRenderGraphNode::FinaliseBatch() + void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex) { - batcher.FinaliseBatches(logicalDeviceHdl); + batcher.FinaliseBatches(logicalDeviceHdl, frameIndex); } /***************************************************************************/ @@ -702,7 +716,7 @@ namespace SHADE // 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. - 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). std::unordered_map resourceAttLayouts; @@ -716,7 +730,7 @@ namespace SHADE { 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; else resourceAttLayouts[color.attachment] = color.layout; @@ -735,6 +749,7 @@ namespace SHADE att.initialLayout = vk::ImageLayout::eUndefined; att.finalLayout = resourceAttLayouts[i]; } + ++i; } // at this point all attachment descs will have their final layouts initialized as if they were standalone and did @@ -843,7 +858,7 @@ namespace SHADE for (auto& inputAtt : subpass->inputReferences) { 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); else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL) depthRead |= (1 << i); @@ -946,25 +961,6 @@ namespace SHADE } } - /***************************************************************************/ - /*! - - \brief - Configures command pools and command buffers. - - */ - /***************************************************************************/ - void SHRenderGraph::ConfigureCommands(void) noexcept - { - //commandPools.resize (static_cast(swapchainHdl->GetNumImages())); - commandBuffers.resize(static_cast(swapchainHdl->GetNumImages())); - - for (uint32_t i = 0; i < commandBuffers.size(); ++i) - { - commandBuffers[i] = commandPools[i]->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); - } - } - /***************************************************************************/ /*! @@ -980,12 +976,11 @@ namespace SHADE */ /***************************************************************************/ - void SHRenderGraph::Init(Handle const& logicalDevice, Handle const& swapchain, std::vector> const& cmdPools, Handle inGlobalData) noexcept + void SHRenderGraph::Init(Handle const& logicalDevice, Handle const& swapchain, Handle inGlobalData) noexcept { logicalDeviceHdl = logicalDevice; swapchainHdl = swapchain; globalData = inGlobalData; - commandPools = cmdPools; } /***************************************************************************/ @@ -1010,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; + } + /***************************************************************************/ /*! @@ -1087,40 +1110,24 @@ namespace SHADE ConfigureSubpasses(); ConfigureRenderpasses(); ConfigureFramebuffers(); - ConfigureCommands(); } // TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a // better way to manage these - void SHRenderGraph::Execute(uint32_t frameIndex, std::initializer_list, uint32_t>> graphScopeBuffers) noexcept + void SHRenderGraph::Execute(uint32_t frameIndex, Handle cmdBuffer) noexcept { - //commandPools[frameIndex]->Reset(); - - auto& cmdBuffer = commandBuffers[frameIndex]; - cmdBuffer->BeginRecording(); - // TODO: DON'T HARDCODE THIS cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080); - for (auto& [buffer, bindingPoint]: graphScopeBuffers) - { - if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer) - cmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0); - else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer) - cmdBuffer->BindIndexBuffer(buffer, 0); - } - for (auto& node : nodes) node->Execute(cmdBuffer, frameIndex); - - cmdBuffer->EndRecording(); } - void SHRenderGraph::FinaliseBatch() + void SHRenderGraph::FinaliseBatch(uint32_t frameIndex) { for (auto& node : nodes) { - node->FinaliseBatch(); + node->FinaliseBatch(frameIndex); } } @@ -1132,9 +1139,5 @@ namespace SHADE return {}; } - Handle const& SHRenderGraph::GetCommandBuffer(uint32_t frameIndex) const noexcept - { - return commandBuffers[frameIndex]; - } } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index 0ecda65a..45624436 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -137,9 +137,11 @@ namespace SHADE void AddInput(std::string resourceToReference) noexcept; // Runtime functions - void Execute(Handle& commandBuffer) noexcept; + void Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept; void AddExteriorDrawCalls(std::function&)> const& newDrawCall) noexcept; + void Init (ResourceManager& resourceManager) noexcept; + /*-----------------------------------------------------------------------*/ /* GETTERS AND SETTERS */ /*-----------------------------------------------------------------------*/ @@ -230,7 +232,7 @@ namespace SHADE // TODO: RemoveSubpass() void Execute (Handle& commandBuffer, uint32_t frameIndex) noexcept; Handle GetOrCreatePipeline (std::pair, Handle> const& vsFsPair, Handle subpass) noexcept; - void FinaliseBatch(); + void FinaliseBatch(uint32_t frameIndex); /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ @@ -250,7 +252,6 @@ namespace SHADE void ConfigureSubpasses (void) noexcept; void ConfigureRenderpasses (void) noexcept; void ConfigureFramebuffers (void) noexcept; - void ConfigureCommands (void) noexcept; /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -271,12 +272,6 @@ namespace SHADE //! Resource library for graph handles ResourceManager resourceManager; - - //! Command pool for the render graph. DO NOT RESET OR FREE THESE, THEY ARE NON-OWNING. TODO: If application is multithreaded, we need more pools. - std::vector> commandPools; - - //! Command buffers for the render graph - std::vector> commandBuffers; //! Handle to global data Handle globalData; @@ -286,22 +281,23 @@ namespace SHADE /* CTORS AND DTORS */ /*-----------------------------------------------------------------------*/ SHRenderGraph (void) noexcept; + SHRenderGraph(SHRenderGraph&& rhs) noexcept; + SHRenderGraph& operator=(SHRenderGraph&& rhs) noexcept; /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - void Init (Handle const& logicalDevice, Handle const& swapchain, std::vector> const& cmdPools, Handle inGlobalData) noexcept; + void Init (Handle const& logicalDevice, Handle const& swapchain, Handle inGlobalData) noexcept; void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageCreateFlagBits createFlags = {}); Handle AddNode (std::string nodeName, std::initializer_list resourceNames, std::initializer_list predecessorNodes) noexcept; void Generate (void) noexcept; - void Execute (uint32_t frameIndex, std::initializer_list, uint32_t>> graphScopeBuffers) noexcept; - void FinaliseBatch(); + void Execute (uint32_t frameIndex, Handle cmdBuffer) noexcept; + void FinaliseBatch(uint32_t frameIndex); /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ /*-----------------------------------------------------------------------*/ Handle GetNode (std::string const& nodeName) const noexcept; - Handle const& GetCommandBuffer (uint32_t frameIndex) const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.cpp b/SHADE_Engine/src/Graphics/SHVkUtil.cpp index c570caf2..e4f9f37e 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.cpp +++ b/SHADE_Engine/src/Graphics/SHVkUtil.cpp @@ -71,4 +71,14 @@ namespace SHADE ); } } + + BindingAndSetHash SHVkUtil::GenBindingSetHash(uint32_t set, uint32_t binding) noexcept + { + // Find the target writeDescSet + BindingAndSetHash writeHash = binding; + writeHash |= static_cast(set) << 32; + + return writeHash; + } + } diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.h b/SHADE_Engine/src/Graphics/SHVkUtil.h index 46ebf096..cba5b062 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.h +++ b/SHADE_Engine/src/Graphics/SHVkUtil.h @@ -76,6 +76,8 @@ namespace SHADE */ /***********************************************************************************/ static void EnsureBufferAndCopyHostVisibleData(Handle device, Handle& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage); + + static BindingAndSetHash GenBindingSetHash (uint32_t set, uint32_t binding) noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/SHVulkanDefines.h b/SHADE_Engine/src/Graphics/SHVulkanDefines.h index 542f379d..2f625f7e 100644 --- a/SHADE_Engine/src/Graphics/SHVulkanDefines.h +++ b/SHADE_Engine/src/Graphics/SHVulkanDefines.h @@ -6,6 +6,8 @@ namespace SHADE { using SHQueueFamilyIndex = uint32_t; + using BindingAndSetHash = uint64_t; + using SetIndex = uint32_t; } diff --git a/SHADE_Engine/src/Graphics/SHVulkanIncludes.h b/SHADE_Engine/src/Graphics/SHVulkanIncludes.h index 472226a0..63aa672b 100644 --- a/SHADE_Engine/src/Graphics/SHVulkanIncludes.h +++ b/SHADE_Engine/src/Graphics/SHVulkanIncludes.h @@ -6,5 +6,6 @@ #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_NO_NODISCARD_WARNINGS #include +#include "Graphics/SHVulkanDefines.h" #endif diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h index 88c7a2e1..3986f823 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h +++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h @@ -9,8 +9,6 @@ namespace SHADE { - using BindingAndSetHash = uint64_t; - struct SHShaderDescriptorBindingInfo { private: diff --git a/SHADE_Engine/src/Input/SHInputManagerSystem.cpp b/SHADE_Engine/src/Input/SHInputManagerSystem.cpp new file mode 100644 index 00000000..1beabe3f --- /dev/null +++ b/SHADE_Engine/src/Input/SHInputManagerSystem.cpp @@ -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 +#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(i) == SH_KEYCODE::SHIFT || + static_cast(i) == SH_KEYCODE::CTRL || + static_cast(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(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(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(i); + return true; + } + } + return false; + } + +} //namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Input/SHInputManagerSystem.h b/SHADE_Engine/src/Input/SHInputManagerSystem.h new file mode 100644 index 00000000..77d8f8fd --- /dev/null +++ b/SHADE_Engine/src/Input/SHInputManagerSystem.h @@ -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 +//#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(key)]; + return (keys[static_cast(key)] && !keysLast[static_cast(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(key)]; + return (keysToggle[static_cast(key)] && + !keysToggleLast[static_cast(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(key)]; + if (releasedTime) *releasedTime = keysReleasedTime[static_cast(key)]; + return keys[static_cast(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(key)]; + if (offTime) *offTime = keysToggleOffTime[static_cast(key)]; + return keysToggle[static_cast(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(key)]; + return (!keys[static_cast(key)] && keysLast[static_cast(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(key)]; + return (!keysToggle[static_cast(key)] && + keysToggleLast[static_cast(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(key)]; + } + + //How long has this key been released for + static inline double GetKeyReleasedTime(SH_KEYCODE key) noexcept + { + return keysReleasedTime[static_cast(key)]; + } + + //How long has this key been toggled on for + static inline double GetKeyToggleOnTime(SH_KEYCODE key) noexcept + { + return keysToggleOnTime[static_cast(key)]; + } + + //How long has this keen been toggled off for + static inline double GetKeyToggleOffTime(SH_KEYCODE key) noexcept + { + return keysToggleOffTime[static_cast(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 + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index fada5b70..0c508a34 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -103,17 +103,17 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Script Manipulation Functions */ /*-----------------------------------------------------------------------------------*/ - bool SHScriptEngine::AddScript(const SHEntity& entity, const std::string_view& scriptName) + bool SHScriptEngine::AddScript(EntityID entity, const std::string_view& scriptName) { - return csScriptsAdd(entity.GetEID(), scriptName.data()); + return csScriptsAdd(entity, scriptName.data()); } - void SHScriptEngine::RemoveAllScripts(const SHEntity& entity) + void SHScriptEngine::RemoveAllScripts(EntityID entity) { - csScriptsRemoveAll(entity.GetEID()); + csScriptsRemoveAll(entity); } - void SHScriptEngine::RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy) + void SHScriptEngine::RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy) { - csScriptsRemoveAllImmediately(entity.GetEID(), callOnDestroy); + csScriptsRemoveAllImmediately(entity, callOnDestroy); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 0994bb5d..08852e90 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -116,14 +116,14 @@ namespace SHADE /// True if successfully added. False otherwise with the error logged to the /// console. /// - bool AddScript(const SHEntity& entity, const std::string_view& scriptName); + bool AddScript(EntityID entity, const std::string_view& scriptName); /// /// Removes all Scripts attached to the specified Entity. Does not do anything /// if the specified Entity is invalid or does not have any Scripts /// attached. /// /// The entity to remove the scripts from. - void RemoveAllScripts(const SHEntity& entity); + void RemoveAllScripts(EntityID entity); /// /// Removes all Scripts attached to the specified Entity. Unlike /// RemoveAllScripts(), this removes all the scripts immediately. @@ -135,7 +135,7 @@ namespace SHADE /// Whether or not to call OnDestroy on the scripts. This is ignored if not in /// play mode. /// - void RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy); + void RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy); /*-----------------------------------------------------------------------------*/ /* Script Serialisation Functions */ diff --git a/TempShaderFolder/ShaderDescriptorDefinitions.glsl b/TempShaderFolder/ShaderDescriptorDefinitions.glsl new file mode 100644 index 00000000..c70a9f5b --- /dev/null +++ b/TempShaderFolder/ShaderDescriptorDefinitions.glsl @@ -0,0 +1,11 @@ +#define SET_STATIC_GLOBALS 0 +#define SET_DYNAMIC_GLOBALS 1 +#define SET_HIGH_FREQUENCY_GLOBALS 2 + +#define BINDING_GENERIC_DATA 0 +#define BINDING_IMAGE_AND_SAMPLERS_DATA 1 +#define BINDING_LIGHTS_DATA 0 +#define BINDING_CAMERA_DATA 0 +#define BINDING_BATCHED_PER_INST_DATA 0 + + diff --git a/TempShaderFolder/TestCubeVs.glsl b/TempShaderFolder/TestCubeVs.glsl index f7dce787..b2d52104 100644 --- a/TempShaderFolder/TestCubeVs.glsl +++ b/TempShaderFolder/TestCubeVs.glsl @@ -1,6 +1,8 @@ #version 450 #extension GL_KHR_vulkan_glsl : enable +//#include "ShaderDescriptorDefinitions.glsl" + layout(location = 0) in vec3 aVertexPos; layout(location = 1) in vec2 aUV; layout(location = 2) in vec3 aNormal; @@ -28,6 +30,12 @@ layout(location = 0) out struct } Out; +layout(set = 2, binding = 0) uniform CameraData +{ + vec4 position; + mat4 vpMat; +} cameraData; + void main() { //const float gamma = testPushConstant.eyePosition.w; @@ -48,6 +56,7 @@ void main() //Out.uv = aUV; // render NDC first - gl_Position = vec4(aVertexPos, 1.0); + //gl_Position = vec4(aVertexPos, 1.0f); + gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); Out.vertColor = vec4 (aVertexPos, 1.0f); } \ No newline at end of file diff --git a/TempShaderFolder/TestCubeVs.spv b/TempShaderFolder/TestCubeVs.spv index 2b0d3b93..eb9a1209 100644 Binary files a/TempShaderFolder/TestCubeVs.spv and b/TempShaderFolder/TestCubeVs.spv differ