|
|
|
@ -37,40 +37,50 @@ namespace SHADE
|
|
|
|
|
/* SHBatch - Constructors/Destructors */
|
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
|
|
|
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
|
|
|
|
: pipeline{ pipeline }
|
|
|
|
|
: pipeline{ pipeline }
|
|
|
|
|
{
|
|
|
|
|
if (!pipeline)
|
|
|
|
|
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
|
|
|
|
|
setAllDirtyFlags();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SHBatch::SHBatch(SHBatch&& rhs)
|
|
|
|
|
: device { rhs.device }
|
|
|
|
|
, pipeline { rhs.pipeline }
|
|
|
|
|
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
|
|
|
|
|
, matBufferDirty { std::move(rhs.matBufferDirty) }
|
|
|
|
|
, subBatches { std::move(rhs.subBatches) }
|
|
|
|
|
, isDirty { std::move(rhs.isDirty) }
|
|
|
|
|
, drawData { std::move(rhs.drawData) }
|
|
|
|
|
, transformData { std::move(rhs.transformData) }
|
|
|
|
|
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
|
|
|
|
|
, matPropsData { std::move(rhs.matPropsData) }
|
|
|
|
|
, matPropsDataSize { rhs.matPropsDataSize }
|
|
|
|
|
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
|
|
|
|
|
, singleMatPropSize { rhs.singleMatPropSize }
|
|
|
|
|
, isCPUBuffersDirty { rhs.isCPUBuffersDirty }
|
|
|
|
|
, drawDataBuffer { rhs.drawDataBuffer }
|
|
|
|
|
, transformDataBuffer { rhs.transformDataBuffer }
|
|
|
|
|
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
|
|
|
|
|
, matPropsBuffer { rhs.matPropsBuffer }
|
|
|
|
|
, instanceDataDescSet { rhs.instanceDataDescSet }
|
|
|
|
|
: device { rhs.device }
|
|
|
|
|
, isAnimated { rhs.isAnimated }
|
|
|
|
|
, pipeline { rhs.pipeline }
|
|
|
|
|
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
|
|
|
|
|
, matBufferDirty { std::move(rhs.matBufferDirty) }
|
|
|
|
|
, subBatches { std::move(rhs.subBatches) }
|
|
|
|
|
, isDirty { std::move(rhs.isDirty) }
|
|
|
|
|
, drawData { std::move(rhs.drawData) }
|
|
|
|
|
, transformData { std::move(rhs.transformData) }
|
|
|
|
|
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
|
|
|
|
|
, matPropsData { std::move(rhs.matPropsData) }
|
|
|
|
|
, matPropsDataSize { rhs.matPropsDataSize }
|
|
|
|
|
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
|
|
|
|
|
, singleMatPropSize { rhs.singleMatPropSize }
|
|
|
|
|
, boneMatrixData { std::move(rhs.boneMatrixData) }
|
|
|
|
|
, boneMatrixIndices { std::move(rhs.boneMatrixIndices) }
|
|
|
|
|
, isCPUBuffersDirty { rhs.isCPUBuffersDirty }
|
|
|
|
|
, drawDataBuffer { rhs.drawDataBuffer }
|
|
|
|
|
, transformDataBuffer { rhs.transformDataBuffer }
|
|
|
|
|
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
|
|
|
|
|
, matPropsBuffer { rhs.matPropsBuffer }
|
|
|
|
|
, boneMatrixBuffer { rhs.boneMatrixBuffer }
|
|
|
|
|
, boneMatrixFirstIndexBuffer { rhs.boneMatrixFirstIndexBuffer }
|
|
|
|
|
, instanceDataDescSet { rhs.instanceDataDescSet }
|
|
|
|
|
{
|
|
|
|
|
rhs.drawDataBuffer = {};
|
|
|
|
|
rhs.transformDataBuffer = {};
|
|
|
|
|
rhs.instancedIntegerBuffer = {};
|
|
|
|
|
rhs.matPropsBuffer = {};
|
|
|
|
|
rhs.drawDataBuffer = {};
|
|
|
|
|
rhs.transformDataBuffer = {};
|
|
|
|
|
rhs.instancedIntegerBuffer = {};
|
|
|
|
|
rhs.matPropsBuffer = {};
|
|
|
|
|
rhs.boneMatrixBuffer = {};
|
|
|
|
|
rhs.boneMatrixFirstIndexBuffer = {};
|
|
|
|
|
rhs.instanceDataDescSet = {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -79,31 +89,38 @@ namespace SHADE
|
|
|
|
|
if (this == &rhs)
|
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
|
|
device = rhs.device ;
|
|
|
|
|
pipeline = rhs.pipeline ;
|
|
|
|
|
referencedMatInstances = std::move(rhs.referencedMatInstances);
|
|
|
|
|
matBufferDirty = std::move(rhs.matBufferDirty) ;
|
|
|
|
|
subBatches = std::move(rhs.subBatches) ;
|
|
|
|
|
isDirty = std::move(rhs.isDirty) ;
|
|
|
|
|
drawData = std::move(rhs.drawData) ;
|
|
|
|
|
transformData = std::move(rhs.transformData) ;
|
|
|
|
|
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
|
|
|
|
|
matPropsData = std::move(rhs.matPropsData) ;
|
|
|
|
|
matPropsDataSize = rhs.matPropsDataSize ;
|
|
|
|
|
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
|
|
|
|
|
singleMatPropSize = rhs.singleMatPropSize ;
|
|
|
|
|
isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
|
|
|
|
|
drawDataBuffer = rhs.drawDataBuffer ;
|
|
|
|
|
transformDataBuffer = rhs.transformDataBuffer ;
|
|
|
|
|
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
|
|
|
|
|
matPropsBuffer = rhs.matPropsBuffer ;
|
|
|
|
|
instanceDataDescSet = rhs.instanceDataDescSet ;
|
|
|
|
|
device = rhs.device ;
|
|
|
|
|
isAnimated = rhs.isAnimated ;
|
|
|
|
|
pipeline = rhs.pipeline ;
|
|
|
|
|
referencedMatInstances = std::move(rhs.referencedMatInstances);
|
|
|
|
|
matBufferDirty = std::move(rhs.matBufferDirty) ;
|
|
|
|
|
subBatches = std::move(rhs.subBatches) ;
|
|
|
|
|
isDirty = std::move(rhs.isDirty) ;
|
|
|
|
|
drawData = std::move(rhs.drawData) ;
|
|
|
|
|
transformData = std::move(rhs.transformData) ;
|
|
|
|
|
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
|
|
|
|
|
matPropsData = std::move(rhs.matPropsData) ;
|
|
|
|
|
matPropsDataSize = rhs.matPropsDataSize ;
|
|
|
|
|
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
|
|
|
|
|
singleMatPropSize = rhs.singleMatPropSize ;
|
|
|
|
|
boneMatrixData = std::move(rhs.boneMatrixData) ;
|
|
|
|
|
boneMatrixIndices = std::move(rhs.boneMatrixIndices) ;
|
|
|
|
|
isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
|
|
|
|
|
drawDataBuffer = rhs.drawDataBuffer ;
|
|
|
|
|
transformDataBuffer = rhs.transformDataBuffer ;
|
|
|
|
|
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
|
|
|
|
|
matPropsBuffer = rhs.matPropsBuffer ;
|
|
|
|
|
boneMatrixBuffer = rhs.boneMatrixBuffer ;
|
|
|
|
|
boneMatrixFirstIndexBuffer = rhs.boneMatrixFirstIndexBuffer ;
|
|
|
|
|
instanceDataDescSet = rhs.instanceDataDescSet ;
|
|
|
|
|
|
|
|
|
|
// Unset values
|
|
|
|
|
rhs.drawDataBuffer = {};
|
|
|
|
|
rhs.transformDataBuffer = {};
|
|
|
|
|
rhs.instancedIntegerBuffer = {};
|
|
|
|
|
rhs.matPropsBuffer = {};
|
|
|
|
|
rhs.drawDataBuffer = {};
|
|
|
|
|
rhs.transformDataBuffer = {};
|
|
|
|
|
rhs.instancedIntegerBuffer = {};
|
|
|
|
|
rhs.matPropsBuffer = {};
|
|
|
|
|
rhs.boneMatrixBuffer = {};
|
|
|
|
|
rhs.boneMatrixFirstIndexBuffer = {};
|
|
|
|
|
rhs.instanceDataDescSet = {};
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
@ -382,6 +399,10 @@ namespace SHADE
|
|
|
|
|
|
|
|
|
|
void SHBatch::UpdateAnimationBuffer(uint32_t frameIndex)
|
|
|
|
|
{
|
|
|
|
|
// Not animated pipeline, we skip
|
|
|
|
|
if (!isAnimated)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Frame Index check
|
|
|
|
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
|
|
|
|
{
|
|
|
|
@ -392,6 +413,9 @@ namespace SHADE
|
|
|
|
|
// Reset Animation Matrix Data
|
|
|
|
|
boneMatrixData.clear();
|
|
|
|
|
|
|
|
|
|
// Add the first identity matrix into the bone matrix data
|
|
|
|
|
boneMatrixData.emplace_back(SHMatrix::Identity);
|
|
|
|
|
|
|
|
|
|
// Populate on the CPU
|
|
|
|
|
for (auto& subBatch : subBatches)
|
|
|
|
|
for (auto rendId : subBatch.Renderables)
|
|
|
|
@ -402,6 +426,7 @@ namespace SHADE
|
|
|
|
|
const auto& MATRICES = animator->GetBoneMatrices();
|
|
|
|
|
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
|
|
|
|
@ -446,13 +471,21 @@ namespace SHADE
|
|
|
|
|
// - EID data
|
|
|
|
|
instancedIntegerData.reserve(numTotalElements);
|
|
|
|
|
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
|
|
|
|
|
auto const& DESC_MAPPINGS = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
|
|
|
|
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,
|
|
|
|
|
vk::ShaderStageFlagBits::eFragment
|
|
|
|
|
);
|
|
|
|
@ -470,9 +503,12 @@ namespace SHADE
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// - Bone Data
|
|
|
|
|
boneMatrixData.clear();
|
|
|
|
|
boneMatrixIndices.clear();
|
|
|
|
|
boneMatrixIndices.reserve(numTotalElements);
|
|
|
|
|
if (isAnimated)
|
|
|
|
|
{
|
|
|
|
|
boneMatrixData.clear();
|
|
|
|
|
boneMatrixIndices.clear();
|
|
|
|
|
boneMatrixIndices.reserve(numTotalElements);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build Sub Batches
|
|
|
|
|
uint32_t nextInstanceIndex = 0;
|
|
|
|
@ -548,12 +584,20 @@ namespace SHADE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bone Data
|
|
|
|
|
auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId);
|
|
|
|
|
if (animator)
|
|
|
|
|
if (isAnimated)
|
|
|
|
|
{
|
|
|
|
|
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());
|
|
|
|
|
auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId);
|
|
|
|
|
if (animator)
|
|
|
|
|
{
|
|
|
|
|
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"
|
|
|
|
|
);
|
|
|
|
|
// - Bone Matrix Indices
|
|
|
|
|
if (!boneMatrixIndices.empty())
|
|
|
|
|
if (isAnimated)
|
|
|
|
|
{
|
|
|
|
|
const uint32_t BMI_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t));
|
|
|
|
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
|
|
@ -625,7 +669,7 @@ namespace SHADE
|
|
|
|
|
|
|
|
|
|
// Bind all required objects before drawing
|
|
|
|
|
std::vector<uint32_t> dynamicOffset{ 0 };
|
|
|
|
|
if (!boneMatrixData.empty())
|
|
|
|
|
if (isAnimated)
|
|
|
|
|
{
|
|
|
|
|
dynamicOffset.emplace_back(0);
|
|
|
|
|
}
|
|
|
|
@ -633,7 +677,7 @@ namespace SHADE
|
|
|
|
|
cmdBuffer->BindPipeline(pipeline);
|
|
|
|
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[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);
|
|
|
|
|
}
|
|
|
|
@ -701,12 +745,14 @@ namespace SHADE
|
|
|
|
|
{
|
|
|
|
|
layoutTypes = PreDefDescLayoutType::MATERIALS;
|
|
|
|
|
}
|
|
|
|
|
if (!boneMatrixData.empty())
|
|
|
|
|
if (isAnimated)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
if (!instanceDataDescSet[frameIndex])
|
|
|
|
@ -756,7 +802,7 @@ namespace SHADE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Animation Bone Data */
|
|
|
|
|
if (!boneMatrixData.empty())
|
|
|
|
|
if (MUST_BUILD_ANIM_BUFFER)
|
|
|
|
|
{
|
|
|
|
|
// Update GPU Buffers
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|