Added Batcher classes and fixed errors

This commit is contained in:
Kah Wei 2022-09-17 23:32:29 +08:00
parent c1a3a6acf1
commit 1c8a434b26
34 changed files with 907 additions and 120 deletions

View File

@ -37,7 +37,9 @@ namespace Sandbox
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::SHGraphicsSystemRoutine>(1);
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>(1);
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>(1);
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>(1);
graphicsSystem->SetWindow(&window);

View File

@ -11,13 +11,14 @@
#pragma once
#include "../SHECSMacros.h"
#include "SH_API.h"
namespace SHADE
{
class SHSystemManager;
class SHSystem
class SH_API SHSystem
{
private:
SystemID systemID;

View File

@ -7,6 +7,7 @@
#include "SHRoutineStats.h"
#include "SHSystem.h"
#include <string>
#include "SH_API.h"
namespace SHADE
@ -15,7 +16,7 @@ namespace SHADE
class SHSystemManager;
class SHSystemRoutine
class SH_API SHSystemRoutine
{
friend class SHSystemManager;
protected:

View File

@ -43,8 +43,8 @@ namespace SHADE
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
auto renderPass = gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetRenderpass();
ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass());
/*auto renderPass = gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetRenderpass();
ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass());*/
imguiCommandBuffer->BeginRecording();
ImGui_ImplVulkan_CreateFontsTexture(imguiCommandBuffer->GetVkCommandBuffer());
@ -53,9 +53,9 @@ namespace SHADE
ImGui_ImplVulkan_DestroyFontUploadObjects();
gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
/*gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
});
});*/
//ImGuiIO& io = ImGui::GetIO();
//int w, h;

View File

@ -33,8 +33,20 @@ namespace SHADE
};
cmdBufferHdl->GetVkCommandBuffer().copyBuffer(stagingBuffer, vkBuffer, 1, &copyRegion);
}
}
// TODO: Need to destroy staging buffer. Obviously not here but after the command has finished executing.
void SHVkBuffer::ResizeNoCopy(uint32_t newSize)
{
Destroy();
vk::Buffer tempBuffer;
std::tie(tempBuffer, std::ignore) = createBuffer(newSize);
vkBuffer = tempBuffer;
}
void SHVkBuffer::ResizeReplace(uint32_t newSize, void* data, uint32_t srcSize)
{
Destroy();
Init(newSize, data, srcSize, bufferUsageFlags, allocCreateInfo.usage, allocCreateInfo.flags);
}
vk::Buffer SHVkBuffer::GetVkBuffer(void) const noexcept
@ -195,12 +207,12 @@ namespace SHADE
// results of allocation
VmaAllocation stagingAlloc;
// To get around VMA's usage for C version of vulkan, create a temp first...,
// To get around VMA's usage for C version of Vulkan, create a temp first...,
VkBuffer tempBuffer{};
// Create the buffer...
vmaCreateBuffer(vmaAllocator,
&bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use renderdoc to check buffer variables?)
&bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use RenderDoc to check buffer variables?)
&allocCreateInfo,
&tempBuffer, &stagingAlloc, &allocInfo);
@ -221,6 +233,32 @@ namespace SHADE
vmaUnmapMemory(vmaAllocator, stagingAlloc);
}
std::pair<vk::Buffer, VmaAllocationInfo> SHVkBuffer::createBuffer(uint32_t size)
{
// Modify the size based on the parameter
sizeStored = size;
bufferCreateInfo.size = sizeStored;
// parameters of a vmaAllocation retrieved via vmaGetAllocationInfo
VmaAllocationInfo allocInfo;
// To get around VMA's usage for C version of vulkan, create a temp first...,
VkBuffer tempBuffer{};
// Create the buffer...
auto result = vmaCreateBuffer(vmaAllocator,
&bufferCreateInfo.operator VkBufferCreateInfo & (),
&allocCreateInfo,
&tempBuffer, &alloc, &allocInfo);
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan buffer. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created buffer. ");
return { tempBuffer, allocInfo };
}
/***************************************************************************/
/*!
@ -238,9 +276,7 @@ namespace SHADE
, randomAccessOptimized{false}
, boundToCoherent {false}
, vmaAllocator{allocator}
{
}
{}
SHVkBuffer::SHVkBuffer(
uint32_t inSize,
@ -266,6 +302,8 @@ namespace SHADE
, boundToCoherent{ rhs.boundToCoherent}
, vmaAllocator{ rhs.vmaAllocator }
, bufferUsageFlags {rhs.bufferUsageFlags}
, bufferCreateInfo { rhs.bufferCreateInfo }
, allocCreateInfo { rhs.allocCreateInfo }
{
rhs.vkBuffer = VK_NULL_HANDLE;
@ -285,6 +323,8 @@ namespace SHADE
boundToCoherent = rhs.boundToCoherent;
vmaAllocator = std::move (rhs.vmaAllocator);
rhs.vkBuffer = VK_NULL_HANDLE;
bufferCreateInfo = rhs.bufferCreateInfo;
allocCreateInfo = rhs.allocCreateInfo;
bufferUsageFlags = rhs.bufferUsageFlags;
return *this;
@ -344,47 +384,26 @@ namespace SHADE
{
sizeStored = inSize;
// For creation of buffer
vk::BufferCreateInfo bufferInfo{};
// Set the buffer flags
bufferUsageFlags = bufferUsage;
// initialize size and usage (vertex, index, uniform, etc)
bufferInfo.size = sizeStored;
bufferInfo.usage = bufferUsage;
bufferInfo.sharingMode = vk::SharingMode::eExclusive;
bufferCreateInfo = vk::BufferCreateInfo{};
bufferCreateInfo.usage = bufferUsageFlags;
bufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
// Prepare allocation parameters for call to create buffers later
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo = VmaAllocationCreateInfo{};
allocCreateInfo.usage = memUsage;
// If vma allocation flags include dedicated bit, immediately activate dst bit
if (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT)
bufferInfo.usage |= vk::BufferUsageFlagBits::eTransferDst;
bufferCreateInfo.usage |= vk::BufferUsageFlagBits::eTransferDst;
allocCreateInfo.flags = allocFlags;
// parameters of a vmaAllocation retrieved via vmaGetAllocationInfo
VmaAllocationInfo allocInfo;
// To get around VMA's usage for C version of vulkan, create a temp first...,
VkBuffer tempBuffer{};
// Create the buffer...
auto result = vmaCreateBuffer(vmaAllocator,
&bufferInfo.operator VkBufferCreateInfo &(),
&allocCreateInfo,
&tempBuffer, &alloc, &allocInfo);
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result (result), "Failed to create vulkan buffer. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created buffer. ");
// ...then assign it to the hpp version
auto [tempBuffer, allocInfo] = createBuffer(sizeStored);
vkBuffer = tempBuffer;
// Set the buffer flags
bufferUsageFlags = bufferInfo.usage;
// This probably means that a HOST_CACHED memory type is used on allocation
if (allocFlags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)
randomAccessOptimized = true;
@ -456,7 +475,7 @@ namespace SHADE
/***************************************************************************/
void SHVkBuffer::Destroy(void) noexcept
{
if (vkBuffer)
vmaDestroyBuffer(vmaAllocator, vkBuffer, alloc);
}
}

View File

@ -47,13 +47,18 @@ namespace SHADE
//! buffer usage info flags
vk::BufferUsageFlags bufferUsageFlags;
vk::BufferCreateInfo bufferCreateInfo;
VmaAllocationCreateInfo allocCreateInfo;
//! Reference to the allocator
//VmaAllocator const& vmaAllocator;
std::reference_wrapper<VmaAllocator const> vmaAllocator;
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void PrepStagingBuffer (void* data, uint32_t srcSize) noexcept;
std::pair<vk::Buffer, VmaAllocationInfo> createBuffer(uint32_t size);
public:
/*-----------------------------------------------------------------------*/
@ -67,8 +72,8 @@ namespace SHADE
uint32_t srcSize,
std::reference_wrapper<VmaAllocator const> allocator,
vk::BufferUsageFlags bufferUsage,
VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags
VmaMemoryUsage memUsage = VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlags allocFlags = {}
) noexcept;
SHVkBuffer(SHVkBuffer&& rhs) noexcept;
SHVkBuffer& operator=(SHVkBuffer&& rhs) noexcept;
@ -93,6 +98,8 @@ namespace SHADE
void WriteToMemory (void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept;
void MapWriteUnmap (void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept;
void TransferToDeviceResource(Handle<SHVkCommandBuffer> const& cmdBufferHdl) noexcept;
void ResizeNoCopy (uint32_t newSize);
void ResizeReplace (uint32_t newSize, void* data, uint32_t srcSize);
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */

View File

@ -451,6 +451,33 @@ namespace SHADE
// //vkCommandBuffer.pipelineBarrier()
//}
/***************************************************************************/
/*!
\brief
Issues a multi indirect draw call.
\param indirectDrawData
SHVkBuffer containing the data for the multi indirect draw call.
\param drawCount
Number of multi indirect draw sub-calls stored in indirectDrawData.
*/
/***************************************************************************/
void SHVkCommandBuffer::DrawMultiIndirect(Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount)
{
if (cmdBufferState != SH_CMD_BUFFER_STATE::RECORDING)
{
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound.");
return;
}
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
}
/***************************************************************************/
/*!

View File

@ -96,7 +96,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
void Reset(void);
// Begins, Ends and Nexts
// Begins and Ends
void BeginRecording (void) noexcept;
void EndRecording (void) noexcept;
void BeginRenderpass (Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkFramebuffer> const& framebufferHdl, vk::Offset2D offset = {0, 0}, vk::Extent2D extent = {0, 0}) noexcept;
@ -127,6 +127,7 @@ namespace SHADE
bool IsReadyToSubmit (void) const noexcept;
void HandlePostSubmit (void) noexcept;
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
// Push Constant variable setting
template <typename T>

View File

@ -0,0 +1,181 @@
/************************************************************************************//*!
\file SHBatch.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief Contains the definition of SHBatch'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 "SHBatch.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/SHVkUtil.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* SHBatch - Usage Functions */
/*---------------------------------------------------------------------------------*/
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
: pipeline { pipeline }
{
if (!pipeline)
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
}
void SHBatch::Add(Handle<SHRenderable> renderable)
{
// Check if we have a SubBatch with the same mesh yet
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
{
return batch.Mesh == renderable->Mesh;
});
// Create one if not found
if (subBatch == subBatches.end())
{
subBatches.emplace_back(renderable->Mesh);
subBatch = subBatches.end() - 1;
}
// Add renderable in
subBatch->Renderables.insert(renderable);
}
void SHBatch::Remove(Handle<SHRenderable> renderable)
{
// Check if we have a SubBatch with the same mesh yet
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
{
return batch.Mesh == renderable->Mesh;
});
// Attempt to remove if it exists
if (subBatch == subBatches.end())
return;
subBatch->Renderables.erase(renderable);
}
void SHBatch::Clear()
{
subBatches.clear();
// Clear CPU buffers
drawData.clear();
transformData.clear();
matPropsData.reset();
matPropsDataSize = 0;
// Clear GPU buffers
drawDataBuffer.Free();
transformDataBuffer.Free();
matPropsBuffer.Free();
}
void SHBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer)
{
// No need to build as there are no changes
if (!isDirty)
return;
// Count number of elements
size_t numTotalElements = 0;
for (const auto& subBatch : subBatches)
{
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 Byte SINGLE_MAT_PROPS_SIZE = pipeline->GetPipelineLayout()->GetShaderBlockInterface
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
vk::ShaderStageFlagBits::eFragment
)->GetBytesRequired();
const Byte MATPROPS_TOTAL_BYTES = drawData.size() * SINGLE_MAT_PROPS_SIZE;
if (matPropsDataSize < MATPROPS_TOTAL_BYTES)
{
matPropsData.reset(new char[MATPROPS_TOTAL_BYTES]);
matPropsDataSize = MATPROPS_TOTAL_BYTES;
}
// Build Sub Batches
uint32_t nextInstanceIndex = 0;
char* propsCurrPtr = matPropsData.get();
for (auto& subBatch : subBatches)
{
// Create command
drawData.emplace_back(vk::DrawIndexedIndirectCommand
{
.indexCount = subBatch.Mesh->IndexCount,
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
.firstIndex = subBatch.Mesh->FirstIndex,
.vertexOffset = subBatch.Mesh->FirstVertex,
.firstInstance = nextInstanceIndex
});
// Fill in buffers (CPU)
for (Handle<SHRenderable> renderable : subBatch.Renderables)
{
// Transform
transformData.emplace_back(renderable->TransformMatrix);
// Material Properties
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
propsCurrPtr += SINGLE_MAT_PROPS_SIZE;
}
}
// Send all buffered data to the GPU buffers
using BuffUsage = vk::BufferUsageFlagBits;
// - Draw Data
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, drawDataBuffer, drawData.data(), DRAW_DATA_BYTES,
BuffUsage::eIndirectBuffer
);
// - Transform Buffer
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, transformDataBuffer, transformData.data(), TF_DATA_BYTES,
BuffUsage::eVertexBuffer
);
// - Material Properties Buffer
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, matPropsBuffer, matPropsData.get(), static_cast<uint32_t>(MATPROPS_TOTAL_BYTES),
BuffUsage::eStorageBuffer
);
isDirty = false;
}
/*---------------------------------------------------------------------------------*/
/* SHBatch - Usage Functions */
/*---------------------------------------------------------------------------------*/
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer)
{
cmdBuffer->DrawMultiIndirect(drawDataBuffer, static_cast<uint32_t>(drawData.size()));
}
}

View File

@ -0,0 +1,101 @@
/************************************************************************************//*!
\file SHBatch.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief Contains the definition of SHSubBatch and SHBatch.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// STL Includes
#include <unordered_set>
// External Dependencies
#include "Graphics/SHVulkanIncludes.h"
// Project Includes
#include "Resource/Handle.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Math/SHMatrix.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkBuffer;
class SHVkCommandBuffer;
class SHVkPipeline;
class SHMesh;
class SHRenderable;
class SHVkLogicalDevice;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Describes a segment of the sub batch operation.
*/
/***********************************************************************************/
struct SHSubBatch
{
public:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<SHMesh> Mesh;
std::unordered_set<Handle<SHRenderable>> Renderables;
};
/***********************************************************************************/
/*!
\brief
Describes a segment of the sub batch operation.
*/
/***********************************************************************************/
class SHBatch
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHBatch(Handle<SHVkPipeline> pipeline);
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
void Add(Handle<SHRenderable> renderable);
void Remove(Handle<SHRenderable> renderable);
void Clear();
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer);
void Draw(Handle<SHVkCommandBuffer> cmdBuffer);
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Batch Properties
Handle<SHVkPipeline> pipeline;
// Batch Tree
std::vector<SHSubBatch> subBatches;
bool isDirty = true;
// CPU Buffers
std::vector<vk::DrawIndexedIndirectCommand> drawData;
std::vector<SHMatrix> transformData;
std::unique_ptr<char> matPropsData;
Byte matPropsDataSize = 0;
// GPU Buffers
Handle<SHVkBuffer> drawDataBuffer;
Handle<SHVkBuffer> transformDataBuffer;
Handle<SHVkBuffer> matPropsBuffer;
};
}

View File

@ -0,0 +1,107 @@
/************************************************************************************//*!
\file SHBatcher.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief
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 "SHBatcher.h"
// STL Includes
#include <vector>
// Project Includes
#include "SHSuperBatch.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
void SHBatcher::Init(const std::vector<SHRenderable>& _renderables, Handle<SHRenderGraph> _renderGraph)
{
renderables = &_renderables;
renderGraph = _renderGraph;
}
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
void SHBatcher::PrepareBatches()
{
// Iterate through all renderables and send it into the batching
for (auto iter = renderables->cbegin(); iter != renderables->cend(); ++iter)
{
AddToBatch(iter->GetHandle());
}
}
void SHBatcher::AddToBatch(Handle<SHRenderable> renderable)
{
// Get Subpass Index for this renderables pipeline
const SHSubPassIndex SUB_PASS_IDX = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpassIndex();
// Check if there is a SuperBatch for the specific RenderPass
auto superBatch = std::find_if(superBatches.begin(), superBatches.end(), [&](const SHSuperBatch& superBatch)
{
return superBatch.GetSubpassId() == SUB_PASS_IDX;
});
// Create if it doesn't exist
if (superBatch == superBatches.end())
{
superBatches.emplace_back(SUB_PASS_IDX);
superBatch = superBatches.end();
}
// Add the Renderable
superBatch->Add(renderable->GetHandle());
}
void SHBatcher::RemoveFromBatch(Handle<SHRenderable> renderable)
{
// Get Subpass Index for this renderables pipeline
const SHSubPassIndex SUB_PASS_IDX = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpassIndex();
// Check if there is a SuperBatch for the specific RenderPass
auto superBatch = std::find_if(superBatches.begin(), superBatches.end(), [&](const SHSuperBatch& superBatch)
{
return superBatch.GetSubpassId() == SUB_PASS_IDX;
});
// Remove if it exists
if (superBatch == superBatches.end())
return;
superBatch->Remove(renderable);
}
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer)
{
// Build SuperBatches
for (auto& batch : superBatches)
{
batch.Build(device, cmdBuffer);
}
}
void SHBatcher::ClearBatches()
{
for (auto& batch : superBatches)
{
batch.Clear();
}
superBatches.clear();
}
}

View File

@ -0,0 +1,63 @@
/************************************************************************************//*!
\file SHBatcher.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief
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 <vector>
// Project Includes
#include "Resource/Handle.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHRenderable;
class SHRenderGraph;
class SHSuperBatch;
class SHVkLogicalDevice;
class SHVkCommandBuffer;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Handles batching of all Renderables assigned to a specific Renderer.
*/
/***********************************************************************************/
class SHBatcher
{
public:
/*-----------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*-----------------------------------------------------------------------------*/
void Init(const std::vector<SHRenderable>& _renderables, Handle<SHRenderGraph> _renderGraph);
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
void PrepareBatches();
void AddToBatch(Handle<SHRenderable> renderable);
void RemoveFromBatch(Handle<SHRenderable> renderable);
void FinaliseBatches(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer);
void ClearBatches();
private:
const std::vector<SHRenderable>* renderables = nullptr;
Handle<SHRenderGraph> renderGraph;
// Children
std::vector<SHSuperBatch> superBatches;
};
}

View File

@ -0,0 +1,99 @@
/************************************************************************************//*!
\file SHSuperBatch.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 8, 2022
\brief Contains the definition of SHSuperBatch'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 "SHSuperBatch.h"
#include "SHBatch.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
SHSuperBatch::SHSuperBatch(SHSubPassIndex subPass)
: subpassIndex { subPass }
{}
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
void SHSuperBatch::Add(Handle<SHRenderable> renderable) noexcept
{
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
// Check if we have a batch with the same pipeline first
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
// Create one if not found
if (batch == batches.end())
{
batches.emplace_back(PIPELINE);
batch = batches.end() - 1;
}
// Add renderable in
batch->Add(renderable);
}
void SHSuperBatch::Remove(Handle<SHRenderable> renderable) noexcept
{
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
// Check if we have a Batch with the same pipeline yet
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
// Attempt to remove if it exists
if (batch == batches.end())
return;
batch->Remove(renderable);
}
void SHSuperBatch::Clear() noexcept
{
for (auto& batch : batches)
{
batch.Clear();
}
batches.clear();
}
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
{
// Build all batches
for (auto& batch : batches)
{
batch.Build(device, cmdBuffer);
}
}
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer) noexcept
{
// Build all batches
for (auto& batch : batches)
{
batch.Draw(cmdBuffer);
}
}
}

View File

@ -0,0 +1,76 @@
/************************************************************************************//*!
\file SHSuperBatch.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 8, 2022
\brief Contains the definition of SHSuperBatch.
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
// External Dependencies
#include "Graphics/SHVulkanIncludes.h"
// Project Includes
#include "Resource/Handle.h"
#include "SHBatch.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkBuffer;
class SHVkCommandBuffer;
class SHMesh;
class SHRenderable;
class SHVkLogicalDevice;
class SHSubpass;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Stores and manages data for all of the batches associated with a specific SubPass
within a RenderGraph.
*/
/***********************************************************************************/
class SHSuperBatch
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHSuperBatch(SHSubPassIndex subPass);
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
void Add(Handle<SHRenderable> renderable) noexcept;
void Remove(Handle<SHRenderable> renderable) noexcept;
void Clear() noexcept;
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
void Draw(Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
SHSubPassIndex GetSubpassId() const noexcept { return subpassIndex; };
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Batch Properties
SHSubPassIndex subpassIndex;
// Children
std::vector<SHBatch> batches;
};
}

View File

@ -21,23 +21,23 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
void SHCamera::SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up)
{
const SHVec3 VIEW = (target - pos).Normalized();
const SHVec3 RIGHT = SHVec3::Cross(VIEW, up).Normalized();
const SHVec3 UP = SHVec3::Cross(RIGHT, VIEW);
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, 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(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);
viewMatrix(3, 2) = view.Dot(pos);
isDirty = true;
}
@ -79,32 +79,32 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
SHMathMat4f SHCamera::GetViewMatrix() const
SHMatrix SHCamera::GetViewMatrix() const
{
return viewMatrix;
}
SHMathMat4f SHCamera::GetProjectionMatrix() const
SHMatrix SHCamera::GetProjectionMatrix() const
{
return projMatrix;
}
SHMathMat4f SHCamera::GetViewProjectionMatrix()
SHMatrix SHCamera::GetViewProjectionMatrix()
{
updateMatrices();
return vpMatrix;
}
SHMathMat4f SHCamera::GetInverseViewMatrix() const
SHMatrix SHCamera::GetInverseViewMatrix() const
{
return inverseVpMatrix;
}
SHMathMat4f SHCamera::GetInverseProjectionMatrix() const
SHMatrix SHCamera::GetInverseProjectionMatrix() const
{
return inverseProjMatrix;
}
SHMathMat4f SHCamera::GetInverseViewProjectionMatrix()
SHMatrix SHCamera::GetInverseViewProjectionMatrix()
{
updateMatrices();
return inverseViewMatrix;
@ -138,11 +138,11 @@ namespace SHADE
if (isDirty)
{
vpMatrix = viewMatrix * projMatrix;
inverseVpMatrix = vpMatrix;
inverseVpMatrix.Inverse();
inverseVpMatrix = SHMatrix::Inverse(vpMatrix);
}
}
SHVec3 SHCamera::multiplyHomogenous(const SHMathMat4f& mat, const SHVec3& vec)
SHVec3 SHCamera::multiplyHomogenous(const SHMatrix& mat, const SHVec3& vec)
{
const SHVec4 HOMO_VEC = { vec[0], vec[1], vec[2], 1.0f };
const SHVec4 RESULT = mat * HOMO_VEC;

View File

@ -75,6 +75,6 @@ namespace SHADE
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
void updateMatrices();
static SHVec3 multiplyHomogenous(const SHMatrix& mat, const SHMatrix& vec);
static SHVec3 multiplyHomogenous(const SHMatrix& mat, const SHVec3& vec);
};
}

View File

@ -46,6 +46,8 @@ namespace SHADE
class SHViewport;
class SHCamera;
class SHVkShaderModule;
class SHMaterial;
class SHMaterialInstance;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */

View File

@ -11,6 +11,10 @@ of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
#include "SHMaterialInstance.h"
#include "SHGraphicsConstants.h"
#include "SHMaterial.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Tools/SHLogger.h"
namespace SHADE
@ -49,14 +53,27 @@ namespace SHADE
for (const auto& data : overrideData)
{
// Get memory offset to the data
SHShaderBlockInterface::Variable variable = SHADER_INFO->GetVariable(data.Index);
const SHShaderBlockInterface::Variable* variable = SHADER_INFO->GetVariable(data.Index);
if (variable == nullptr)
{
SHLOG_WARNING("[SHMaterialInstance] Invalid override data indices provided. Skipping.");
continue;
}
const auto DATA_OFFSET = variable->offset;
memcpy_s(dest + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize);
memcpy(static_cast<char*>(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize);
}
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterialInstance::getShaderBlockInterface() const noexcept
{
return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
vk::ShaderStageFlagBits::eFragment
);
}
}

View File

@ -14,6 +14,7 @@ of DigiPen Institute of Technology is prohibited.
#include <memory>
// Project Includes
#include "Resource/Handle.h"
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
namespace SHADE
{
@ -76,6 +77,11 @@ namespace SHADE
std::vector<OverrideData> overrideData;
std::unique_ptr<char> dataStore;
size_t dataStoreSize = 0;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> getShaderBlockInterface() const noexcept;
};
}

View File

@ -30,12 +30,12 @@ namespace SHADE
// Allocate data store if it was empty
if (dataStore == nullptr)
{
dataStoreSize = SHADER_INFO->GetBytesRequired();dataStoreSize
dataStoreSize = SHADER_INFO->GetBytesRequired();
dataStore.reset(new char[dataStoreSize]);
}
OverrideData od;
od.Index = SHADER_INFO.GetVariableIndex(key);
od.Index = SHADER_INFO->GetVariableIndex(key);
od.DataSize = sizeof(T);
if (overrideData.empty())
{
@ -65,7 +65,7 @@ namespace SHADE
}
// Search Override Data for the property
uint32_t PROP_IDX = SHADER_INFO.GetVariableIndex(key);
uint32_t PROP_IDX = SHADER_INFO->GetVariableIndex(key);
auto prop = std::find(overrideData.begin(), overrideData.end(), [&](const OverrideData& data)
{
return PROP_IDX == data.Index;

View File

@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes
#include "Resource/Handle.h"
#include "Resource/ResourceLibrary.h"
#include "SHVertex.h"
#include "Math/SHMath.h"
namespace SHADE
{
@ -44,10 +44,10 @@ namespace SHADE
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
using Index = uint32_t;
using VertexPosition = SHMathVec3f;
using VertexTexCoord = SHMathVec2f;
using VertexTangent = SHMathVec3f;
using VertexNormal = SHMathVec3f;
using VertexPosition = SHVec3;
using VertexTexCoord = SHVec2;
using VertexTangent = SHVec3;
using VertexNormal = SHVec3;
/*-----------------------------------------------------------------------------*/
/* Data Members */

View File

@ -13,6 +13,8 @@ of DigiPen Institute of Technology is prohibited.
#include "SHRenderable.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "SHGraphicsSystem.h"
#include "SHMaterialInstance.h"
namespace SHADE
{

View File

@ -18,7 +18,6 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes
#include "SHCamera.h"
#include "Resource/Handle.h"
#include "SHGraphicsConstants.h"
#include "Graphics/RenderGraph/SHRenderGraph.h"
namespace SHADE

View File

@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Instance/SHVkInstance.h"
#include "Tools/SHLogger.h"
#include "SHRenderer.h"
#include "Resource/ResourceLibrary.h"
namespace SHADE
{

View File

@ -28,6 +28,7 @@ namespace SHADE
class SHVkCommandBuffer;
class SHVkLogicalDevice;
class SHVkImageView;
class ResourceManager;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */

View File

@ -107,7 +107,7 @@ namespace SHADE
return renderpassHdl;
}
uint32_t SHVkPipelineState::GetSubpassIndex(void) const noexcept
SHSubPassIndex SHVkPipelineState::GetSubpassIndex(void) const noexcept
{
return subpassIndex;
}

View File

@ -208,7 +208,7 @@ namespace SHADE
SHDepthStencilState const& GetDepthStencilState (void) const noexcept;
SHColorBlendState const& GetColorBlenState (void) const noexcept;
Handle<SHVkRenderpass> const& GetRenderpass (void) const noexcept;
uint32_t GetSubpassIndex (void) const noexcept;
SHSubPassIndex GetSubpassIndex (void) const noexcept;
void SetDirty(bool isDirty) noexcept;
};

View File

@ -10,6 +10,10 @@ namespace SHADE
{
class SHVkLogicalDevice;
class SHVkFramebuffer;
/*-----------------------------------------------------------------------*/
/* TYPE DEFINTIIONS */
/*-----------------------------------------------------------------------*/
using SHSubPassIndex = uint32_t;
class SHVkRenderpass
{

View File

@ -1,6 +1,10 @@
#include "SHPch.h"
#include "SHVkUtil.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
namespace SHADE
{
@ -19,4 +23,29 @@ namespace SHADE
IsDepthOnlyFormat(format);
}
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
{
if (bufferHandle)
{
// Resize
bufferHandle->ResizeReplace(size, src, size);
}
else
{
// Create new
using BuffUsage = vk::BufferUsageFlagBits;
bufferHandle = device->CreateBuffer
(
size,
src,
size,
usage | BuffUsage::eTransferDst,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT
);
}
// Order transfers
bufferHandle->TransferToDeviceResource(cmdBuffer);
}
}

View File

@ -3,13 +3,53 @@
#include "SHVulkanIncludes.h"
#include "Resource/Handle.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkLogicalDevice;
class SHVkCommandBuffer;
class SHVkBuffer;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
class SHVkUtil
{
public:
static bool IsDepthOnlyFormat (vk::Format format) noexcept;
static bool IsDepthStencilAttachment(vk::Format format) noexcept;
/***********************************************************************************/
/*!
\brief
Ensures that the specified bufferHandle contains a buffer that fits the specified
size and creates it if it does not exist. This follows by issuing a transfer
command into the created buffer.
All created buffers will use VMA_MEMORY_USAGE_AUTO and
VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
\param device
Device used to create the SHVkBuffer.
\param cmdBuffer
CommandBuffer which commands for issuing transferring the data to the GPU.
\param bufferHandle
Reference to the handle that holds any existing buffer or will be used to hold the
created buffer.
\param src
Data to copy from.
\param size
Size of data to copy.
\param usage
Usage flags for the buffer.
*/
/***********************************************************************************/
static void EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage);
};
}

View File

@ -1,5 +1,6 @@
#include "SHPch.h"
#include "SHShaderBlockInterface.h"
#include "Tools/SHLogger.h"
namespace SHADE
{
@ -12,14 +13,14 @@ namespace SHADE
SHLOG_WARNING("[SHShaderBlockInterface] Attempted to specify a variable with a duplicate name. This will be ignored.");
return;
}
variableIndexing.emplace_back(std::move(newVariable));
variables.try_emplace (std::move(name), static_cast<uint32_t>(variableIndexing.size() - 1));
variables.emplace_back(std::move(newVariable));
variableIndexing.try_emplace(std::move(name), static_cast<uint32_t>(variables.size() - 1));
}
SHShaderBlockInterface::Variable const* const SHShaderBlockInterface::GetVariable(std::string const& variableName) const noexcept
{
if (variableIndexing.contains(variableName))
return &variables.at(variableIndexing.at(variableName).second);
return &variables.at(variableIndexing.at(variableName));
return nullptr;
}
@ -32,12 +33,12 @@ namespace SHADE
return nullptr;
}
uint32_t SHShaderBlockInterface::GetVariableIndex(std::string const& variableName) const noexcept
uint32_t SHShaderBlockInterface::GetVariableIndex(std::string const& variableName) const
{
if (!variableIndexing.contains(variableName))
throw std::invalid_argument("Attempted to retrieve index to variable that does not exist!");
return variableIndexing.at(variableName).second;
return variableIndexing.at(variableName);
}
SHShaderBlockInterface::SHShaderBlockInterface(void) noexcept
@ -47,7 +48,7 @@ namespace SHADE
SHShaderBlockInterface::SHShaderBlockInterface(SHShaderBlockInterface&& rhs) noexcept
: variables { std::move(rhs.variables) }
, variableIndexing { std::move(rhs.variableIndexing) }
, bytesRequired { std::move (rhs.bytesRequired) }
, bytesRequired { rhs.bytesRequired }
{}
void SHShaderBlockInterface::SetBytesRequired(uint32_t bytes) noexcept
@ -68,7 +69,7 @@ namespace SHADE
variables = std::move(rhs.variables);
variableIndexing = std::move(rhs.variableIndexing);
bytesRequired = std::move(rhs.bytesRequired);
bytesRequired = rhs.bytesRequired;
return *this;
}

View File

@ -14,8 +14,8 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* HandleBase - Overloaded Operators */
/*---------------------------------------------------------------------------------*/
inline HandleBase::operator bool() const
/*---------------------------------------------------------------------------------*/
{
return id.Raw != INVALID_ID.Raw;
}