Fixed missing moves in SHBatch move constructor and assignment as well as added isAnimated check with base 0-index identity matrix for bones

This commit is contained in:
Kah Wei 2023-01-17 19:34:17 +08:00
parent af3e4a3cfd
commit 62e0e5e1ad
3 changed files with 131 additions and 64 deletions

View File

@ -37,40 +37,50 @@ namespace SHADE
/* SHBatch - Constructors/Destructors */ /* SHBatch - Constructors/Destructors */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline) SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
: pipeline{ pipeline } : pipeline{ pipeline }
{ {
if (!pipeline) if (!pipeline)
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!"); throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
// Check the pipeline and flag it depending on whether or not it is animated
isAnimated = checkIfIsAnimatedPipeline(pipeline);
// Mark all as dirty // Mark all as dirty
setAllDirtyFlags(); setAllDirtyFlags();
} }
SHBatch::SHBatch(SHBatch&& rhs) SHBatch::SHBatch(SHBatch&& rhs)
: device { rhs.device } : device { rhs.device }
, pipeline { rhs.pipeline } , isAnimated { rhs.isAnimated }
, referencedMatInstances { std::move(rhs.referencedMatInstances) } , pipeline { rhs.pipeline }
, matBufferDirty { std::move(rhs.matBufferDirty) } , referencedMatInstances { std::move(rhs.referencedMatInstances) }
, subBatches { std::move(rhs.subBatches) } , matBufferDirty { std::move(rhs.matBufferDirty) }
, isDirty { std::move(rhs.isDirty) } , subBatches { std::move(rhs.subBatches) }
, drawData { std::move(rhs.drawData) } , isDirty { std::move(rhs.isDirty) }
, transformData { std::move(rhs.transformData) } , drawData { std::move(rhs.drawData) }
, instancedIntegerData { std::move(rhs.instancedIntegerData) } , transformData { std::move(rhs.transformData) }
, matPropsData { std::move(rhs.matPropsData) } , instancedIntegerData { std::move(rhs.instancedIntegerData) }
, matPropsDataSize { rhs.matPropsDataSize } , matPropsData { std::move(rhs.matPropsData) }
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize } , matPropsDataSize { rhs.matPropsDataSize }
, singleMatPropSize { rhs.singleMatPropSize } , singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
, isCPUBuffersDirty { rhs.isCPUBuffersDirty } , singleMatPropSize { rhs.singleMatPropSize }
, drawDataBuffer { rhs.drawDataBuffer } , boneMatrixData { std::move(rhs.boneMatrixData) }
, transformDataBuffer { rhs.transformDataBuffer } , boneMatrixIndices { std::move(rhs.boneMatrixIndices) }
, instancedIntegerBuffer { rhs.instancedIntegerBuffer } , isCPUBuffersDirty { rhs.isCPUBuffersDirty }
, matPropsBuffer { rhs.matPropsBuffer } , drawDataBuffer { rhs.drawDataBuffer }
, instanceDataDescSet { rhs.instanceDataDescSet } , transformDataBuffer { rhs.transformDataBuffer }
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
, matPropsBuffer { rhs.matPropsBuffer }
, boneMatrixBuffer { rhs.boneMatrixBuffer }
, boneMatrixFirstIndexBuffer { rhs.boneMatrixFirstIndexBuffer }
, instanceDataDescSet { rhs.instanceDataDescSet }
{ {
rhs.drawDataBuffer = {}; rhs.drawDataBuffer = {};
rhs.transformDataBuffer = {}; rhs.transformDataBuffer = {};
rhs.instancedIntegerBuffer = {}; rhs.instancedIntegerBuffer = {};
rhs.matPropsBuffer = {}; rhs.matPropsBuffer = {};
rhs.boneMatrixBuffer = {};
rhs.boneMatrixFirstIndexBuffer = {};
rhs.instanceDataDescSet = {}; rhs.instanceDataDescSet = {};
} }
@ -79,31 +89,38 @@ namespace SHADE
if (this == &rhs) if (this == &rhs)
return *this; return *this;
device = rhs.device ; device = rhs.device ;
pipeline = rhs.pipeline ; isAnimated = rhs.isAnimated ;
referencedMatInstances = std::move(rhs.referencedMatInstances); pipeline = rhs.pipeline ;
matBufferDirty = std::move(rhs.matBufferDirty) ; referencedMatInstances = std::move(rhs.referencedMatInstances);
subBatches = std::move(rhs.subBatches) ; matBufferDirty = std::move(rhs.matBufferDirty) ;
isDirty = std::move(rhs.isDirty) ; subBatches = std::move(rhs.subBatches) ;
drawData = std::move(rhs.drawData) ; isDirty = std::move(rhs.isDirty) ;
transformData = std::move(rhs.transformData) ; drawData = std::move(rhs.drawData) ;
instancedIntegerData = std::move(rhs.instancedIntegerData) ; transformData = std::move(rhs.transformData) ;
matPropsData = std::move(rhs.matPropsData) ; instancedIntegerData = std::move(rhs.instancedIntegerData) ;
matPropsDataSize = rhs.matPropsDataSize ; matPropsData = std::move(rhs.matPropsData) ;
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ; matPropsDataSize = rhs.matPropsDataSize ;
singleMatPropSize = rhs.singleMatPropSize ; singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
isCPUBuffersDirty = rhs.isCPUBuffersDirty ; singleMatPropSize = rhs.singleMatPropSize ;
drawDataBuffer = rhs.drawDataBuffer ; boneMatrixData = std::move(rhs.boneMatrixData) ;
transformDataBuffer = rhs.transformDataBuffer ; boneMatrixIndices = std::move(rhs.boneMatrixIndices) ;
instancedIntegerBuffer = rhs.instancedIntegerBuffer ; isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
matPropsBuffer = rhs.matPropsBuffer ; drawDataBuffer = rhs.drawDataBuffer ;
instanceDataDescSet = rhs.instanceDataDescSet ; transformDataBuffer = rhs.transformDataBuffer ;
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
matPropsBuffer = rhs.matPropsBuffer ;
boneMatrixBuffer = rhs.boneMatrixBuffer ;
boneMatrixFirstIndexBuffer = rhs.boneMatrixFirstIndexBuffer ;
instanceDataDescSet = rhs.instanceDataDescSet ;
// Unset values // Unset values
rhs.drawDataBuffer = {}; rhs.drawDataBuffer = {};
rhs.transformDataBuffer = {}; rhs.transformDataBuffer = {};
rhs.instancedIntegerBuffer = {}; rhs.instancedIntegerBuffer = {};
rhs.matPropsBuffer = {}; rhs.matPropsBuffer = {};
rhs.boneMatrixBuffer = {};
rhs.boneMatrixFirstIndexBuffer = {};
rhs.instanceDataDescSet = {}; rhs.instanceDataDescSet = {};
return *this; return *this;
@ -382,6 +399,10 @@ namespace SHADE
void SHBatch::UpdateAnimationBuffer(uint32_t frameIndex) void SHBatch::UpdateAnimationBuffer(uint32_t frameIndex)
{ {
// Not animated pipeline, we skip
if (!isAnimated)
return;
// Frame Index check // Frame Index check
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{ {
@ -392,6 +413,9 @@ namespace SHADE
// Reset Animation Matrix Data // Reset Animation Matrix Data
boneMatrixData.clear(); boneMatrixData.clear();
// Add the first identity matrix into the bone matrix data
boneMatrixData.emplace_back(SHMatrix::Identity);
// Populate on the CPU // Populate on the CPU
for (auto& subBatch : subBatches) for (auto& subBatch : subBatches)
for (auto rendId : subBatch.Renderables) for (auto rendId : subBatch.Renderables)
@ -402,6 +426,7 @@ namespace SHADE
const auto& MATRICES = animator->GetBoneMatrices(); const auto& MATRICES = animator->GetBoneMatrices();
boneMatrixData.insert(boneMatrixData.end(), MATRICES.cbegin(), MATRICES.cend()); boneMatrixData.insert(boneMatrixData.end(), MATRICES.cbegin(), MATRICES.cend());
} }
// We don't have to account for missing animators or reset indices as the renderable list are not updated at this point
} }
// Update GPU Buffers // Update GPU Buffers
@ -446,13 +471,21 @@ namespace SHADE
// - EID data // - EID data
instancedIntegerData.reserve(numTotalElements); instancedIntegerData.reserve(numTotalElements);
instancedIntegerData.clear(); instancedIntegerData.clear();
if (isAnimated)
{
// - Bone Data
boneMatrixData.clear();
boneMatrixIndices.clear();
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING); // Add the first identity matrix into the bone matrix data
boneMatrixData.emplace_back(SHMatrix::Identity);
}
// - Material Properties Data // - Material Properties Data
auto const& DESC_MAPPINGS = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
( (
descMappings.at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH), DESC_MAPPINGS.at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH),
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA, SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
vk::ShaderStageFlagBits::eFragment vk::ShaderStageFlagBits::eFragment
); );
@ -470,9 +503,12 @@ namespace SHADE
} }
} }
// - Bone Data // - Bone Data
boneMatrixData.clear(); if (isAnimated)
boneMatrixIndices.clear(); {
boneMatrixIndices.reserve(numTotalElements); boneMatrixData.clear();
boneMatrixIndices.clear();
boneMatrixIndices.reserve(numTotalElements);
}
// Build Sub Batches // Build Sub Batches
uint32_t nextInstanceIndex = 0; uint32_t nextInstanceIndex = 0;
@ -548,12 +584,20 @@ namespace SHADE
} }
// Bone Data // Bone Data
auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId); if (isAnimated)
if (animator)
{ {
boneMatrixIndices.emplace_back(static_cast<uint32_t>(boneMatrixData.size())); auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId);
const auto& BONE_MATRICES = animator->GetBoneMatrices(); if (animator)
boneMatrixData.insert(boneMatrixData.end(), BONE_MATRICES.cbegin(), BONE_MATRICES.cend()); {
boneMatrixIndices.emplace_back(static_cast<uint32_t>(boneMatrixData.size()));
const auto& BONE_MATRICES = animator->GetBoneMatrices();
boneMatrixData.insert(boneMatrixData.end(), BONE_MATRICES.cbegin(), BONE_MATRICES.cend());
}
else
{
// Take the first matrix which is always identity
boneMatrixIndices.emplace_back(static_cast<uint32_t>(0));
}
} }
} }
} }
@ -590,7 +634,7 @@ namespace SHADE
"Batch Instance Data Buffer" "Batch Instance Data Buffer"
); );
// - Bone Matrix Indices // - Bone Matrix Indices
if (!boneMatrixIndices.empty()) if (isAnimated)
{ {
const uint32_t BMI_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t)); const uint32_t BMI_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
@ -625,7 +669,7 @@ namespace SHADE
// Bind all required objects before drawing // Bind all required objects before drawing
std::vector<uint32_t> dynamicOffset{ 0 }; std::vector<uint32_t> dynamicOffset{ 0 };
if (!boneMatrixData.empty()) if (isAnimated)
{ {
dynamicOffset.emplace_back(0); dynamicOffset.emplace_back(0);
} }
@ -633,7 +677,7 @@ namespace SHADE
cmdBuffer->BindPipeline(pipeline); cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
if (boneMatrixFirstIndexBuffer[frameIndex]) if (isAnimated && boneMatrixFirstIndexBuffer[frameIndex])
{ {
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::BONE_MATRIX_FIRST_INDEX, boneMatrixFirstIndexBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::BONE_MATRIX_FIRST_INDEX, boneMatrixFirstIndexBuffer[frameIndex], 0);
} }
@ -701,12 +745,14 @@ namespace SHADE
{ {
layoutTypes = PreDefDescLayoutType::MATERIALS; layoutTypes = PreDefDescLayoutType::MATERIALS;
} }
if (!boneMatrixData.empty()) if (isAnimated)
{ {
layoutTypes = PreDefDescLayoutType::MATERIAL_AND_BONES; layoutTypes = PreDefDescLayoutType::MATERIAL_AND_BONES;
} }
if (matPropsData || !boneMatrixData.empty()) const bool MUST_BUILD_ANIM_BUFFER = isAnimated && !boneMatrixData.empty();
if (matPropsData || MUST_BUILD_ANIM_BUFFER)
{ {
// Make sure that we have a descriptor set if we don't already have one // Make sure that we have a descriptor set if we don't already have one
if (!instanceDataDescSet[frameIndex]) if (!instanceDataDescSet[frameIndex])
@ -756,7 +802,7 @@ namespace SHADE
} }
/* Animation Bone Data */ /* Animation Bone Data */
if (!boneMatrixData.empty()) if (MUST_BUILD_ANIM_BUFFER)
{ {
// Update GPU Buffers // Update GPU Buffers
const uint32_t BONE_MTX_DATA_BYTES = static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix)); const uint32_t BONE_MTX_DATA_BYTES = static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix));
@ -786,4 +832,21 @@ namespace SHADE
); );
} }
} }
bool SHBatch::checkIfIsAnimatedPipeline(Handle<SHVkPipeline> pipeline)
{
if (!pipeline || !pipeline->GetPipelineLayout())
return false;
// Grab the pipeline descriptor set layouts
auto pipelineDescLayouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline();
// Check if they contain the material and bones layout, that indicates it is
using GfxPreDefType = SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes;
const Handle<SHVkDescriptorSetLayout> BONE_DESC_SET_LAYOUT = SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(GfxPreDefType::MATERIAL_AND_BONES)[0];
return std::find_if(pipelineDescLayouts.begin(), pipelineDescLayouts.end(), [BONE_DESC_SET_LAYOUT](Handle<SHVkDescriptorSetLayout> layout)
{
return BONE_DESC_SET_LAYOUT == layout;
}) != pipelineDescLayouts.end();
}
} }

View File

@ -111,6 +111,8 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
// Resources // Resources
Handle<SHVkLogicalDevice> device; Handle<SHVkLogicalDevice> device;
// Config
bool isAnimated; // Whether the material supports animation
// Batch Properties // Batch Properties
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances; std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
@ -126,7 +128,7 @@ namespace SHADE
Byte matPropsDataSize = 0; Byte matPropsDataSize = 0;
Byte singleMatPropAlignedSize = 0; Byte singleMatPropAlignedSize = 0;
Byte singleMatPropSize = 0; Byte singleMatPropSize = 0;
std::vector<SHMatrix> boneMatrixData; std::vector<SHMatrix> boneMatrixData; // 0th element is always an identity matrix
std::vector<uint32_t> boneMatrixIndices; std::vector<uint32_t> boneMatrixIndices;
bool isCPUBuffersDirty = true; bool isCPUBuffersDirty = true;
// GPU Buffers // GPU Buffers
@ -143,5 +145,6 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void setAllDirtyFlags(); void setAllDirtyFlags();
void rebuildDescriptorSetBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void rebuildDescriptorSetBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
static bool checkIfIsAnimatedPipeline(Handle<SHVkPipeline> pipeline);
}; };
} }

View File

@ -173,6 +173,7 @@ namespace SHADE
} }
else else
{ {
// Automatically set to index 0, which will be an identity matrix
vertBoneIdxStorage.resize(vertBoneIdxStorage.size() + addJob.VertexCount); vertBoneIdxStorage.resize(vertBoneIdxStorage.size() + addJob.VertexCount);
} }
if (addJob.VertexBoneWeights) if (addJob.VertexBoneWeights)