diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index f281fdb0..9bd5437d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -397,6 +397,10 @@ namespace SHADE void SHBatch::UpdateAnimationBuffer(uint32_t frameIndex) { + // Ignore if not animated batch + if (!isAnimated) + return; + // Frame Index check if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) { @@ -407,6 +411,9 @@ namespace SHADE // Reset Animation Matrix Data boneMatrixData.clear(); + // Add the first identity matrix into the bone matrix data + boneMatrixData.emplace_back(SHMatrix::Identity); // This kills the GPU + // Populate on the CPU for (auto& subBatch : subBatches) for (auto rendId : subBatch.Renderables) @@ -417,6 +424,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 @@ -461,10 +469,19 @@ namespace SHADE // - EID data instancedIntegerData.reserve(numTotalElements); instancedIntegerData.clear(); + // - Bone Data + if (isAnimated) + { + boneMatrixData.clear(); + boneMatrixIndices.clear(); + boneMatrixIndices.reserve(numTotalElements); - 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& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING); const Handle SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface ( descMappings.at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH), @@ -484,10 +501,6 @@ namespace SHADE matPropsDataSize = matPropTotalBytes; } } - // - Bone Data - boneMatrixData.clear(); - boneMatrixIndices.clear(); - boneMatrixIndices.reserve(numTotalElements); // Build Sub Batches uint32_t nextInstanceIndex = 0; @@ -563,12 +576,20 @@ namespace SHADE } // Bone Data - auto animator = SHComponentManager::GetComponent_s(rendId); - if (animator) + if (isAnimated) { - boneMatrixIndices.emplace_back(static_cast(boneMatrixData.size())); - const auto& BONE_MATRICES = animator->GetBoneMatrices(); - boneMatrixData.insert(boneMatrixData.end(), BONE_MATRICES.cbegin(), BONE_MATRICES.cend()); + auto animator = SHComponentManager::GetComponent_s(rendId); + if (animator) + { + boneMatrixIndices.emplace_back(static_cast(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(0)); + } } } } @@ -605,7 +626,7 @@ namespace SHADE "Batch Instance Data Buffer" ); // - Bone Matrix Indices - if (!boneMatrixIndices.empty()) + if (isAnimated && !boneMatrixIndices.empty()) { const uint32_t BMI_DATA_BYTES = static_cast(boneMatrixIndices.size() * sizeof(uint32_t)); SHVkUtil::EnsureBufferAndCopyHostVisibleData @@ -640,7 +661,7 @@ namespace SHADE // Bind all required objects before drawing std::vector dynamicOffset{ 0 }; - if (!boneMatrixData.empty()) + if (isAnimated && !boneMatrixData.empty()) { dynamicOffset.emplace_back(0); } @@ -648,7 +669,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); } @@ -721,7 +742,9 @@ namespace SHADE layoutTypes = PreDefDescLayoutType::MATERIAL_AND_BONES; } - if (matPropsData || !boneMatrixData.empty()) + const bool MUST_BUILD_BONE_DESC = isAnimated && !boneMatrixData.empty(); + + if (matPropsData || MUST_BUILD_BONE_DESC) { // Make sure that we have a descriptor set if we don't already have one if (!instanceDataDescSet[frameIndex]) @@ -771,7 +794,7 @@ namespace SHADE } /* Animation Bone Data */ - if (!boneMatrixData.empty()) + if (MUST_BUILD_BONE_DESC) { // Update GPU Buffers const uint32_t BONE_MTX_DATA_BYTES = static_cast(boneMatrixData.size() * sizeof(SHMatrix)); @@ -801,4 +824,22 @@ namespace SHADE ); } } + + bool SHBatch::checkIfIsAnimatedPipeline(Handle 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 GfxPreDef = SHGraphicsPredefinedData; + using GfxPreDefType = GfxPreDef::PredefinedDescSetLayoutTypes; + const Handle BONE_DESC_SET_LAYOUT = GfxPreDef::GetPredefinedDescSetLayouts(GfxPreDefType::MATERIAL_AND_BONES)[0]; + return std::find_if(pipelineDescLayouts.begin(), pipelineDescLayouts.end(), [BONE_DESC_SET_LAYOUT](Handle layout) + { + return BONE_DESC_SET_LAYOUT == layout; + }) != pipelineDescLayouts.end(); + } }