Use float buffer for skinning (#2009)

* Switching to Buffer<float> instead of Buffer<float3> in the skinning shader because metal doesn't support float3 buffers

Signed-off-by: amzn-tommy <waltont@amazon.com>

* Adding a comment to LinearSkinningPassSRG pointing out that positions, normals, and bitangents are using float buffers to work on Metal

Signed-off-by: amzn-tommy <waltont@amazon.com>
This commit is contained in:
Tommy Walton
2021-07-09 15:54:46 -07:00
committed by GitHub
parent 70810dfbb9
commit 0d82c1e670
3 changed files with 42 additions and 9 deletions
@@ -14,6 +14,15 @@ option enum class SkinningMethod { LinearSkinning, DualQuaternion } o_skinningMe
option bool o_applyMorphTargets = false;
option bool o_applyColorMorphTargets = false;
float3 ReadFloat3FromFloatBuffer(Buffer<float> buffer, uint index)
{
float3 result;
result.x = buffer[index * 3];
result.y = buffer[index * 3 + 1];
result.z = buffer[index * 3 + 2];
return result;
}
// Apply a morph target delta with three components
void ApplyMorphTargetDelta(uint streamOffset, uint vertexIndex, inout float3 modifiedValue)
{
@@ -162,10 +171,10 @@ void MainCS(uint3 thread_id: SV_DispatchThreadID)
return;
}
float3 position = InstanceSrg::m_sourcePositions[i];
float3 normal = InstanceSrg::m_sourceNormals[i];
float4 tangent = InstanceSrg::m_sourceTangents[i];
float3 bitangent = InstanceSrg::m_sourceBiTangents[i];
float3 position = ReadFloat3FromFloatBuffer(InstanceSrg::m_sourcePositions, i);
float3 normal = ReadFloat3FromFloatBuffer(InstanceSrg::m_sourceNormals, i);
float4 tangent = InstanceSrg::m_sourceTangents[i];
float3 bitangent = ReadFloat3FromFloatBuffer(InstanceSrg::m_sourceBiTangents, i);
// Four indices, 16-bits each, stored in 2 32-bit uints
uint2 rawIndices = InstanceSrg::m_sourceBlendIndices.Load2(i * 8);
@@ -20,10 +20,12 @@ ShaderResourceGroup InstanceSrg : SRG_PerDraw
uint m_totalNumberOfThreadsX;
// Per-model input
Buffer<float3> m_sourcePositions; // POSITION 0
Buffer<float3> m_sourceNormals; // NORMAL 0
// Positions, normals, and bitangents are all 3-component per-vertex buffers,
// but Metal doesn't support float3 buffers so Buffer<float> is used instead
Buffer<float> m_sourcePositions; // POSITION 0
Buffer<float> m_sourceNormals; // NORMAL 0
Buffer<float4> m_sourceTangents; // TANGENT 0
Buffer<float3> m_sourceBiTangents; // BITANGENT 0
Buffer<float> m_sourceBiTangents; // BITANGENT 0
ByteAddressBuffer m_sourceBlendIndices; // BLENDINDICES 0
Buffer<float> m_sourceBlendWeights; // BLENDWEIGHTS 0
@@ -118,7 +118,29 @@ namespace AZ
}
m_inputBufferAssets[static_cast<uint8_t>(inputStream)] = bufferAsset;
m_inputBuffers[static_cast<uint8_t>(inputStream)] = RPI::Buffer::FindOrCreate(bufferAsset);
Data::Instance<RPI::Buffer> buffer = RPI::Buffer::FindOrCreate(bufferAsset);
m_inputBuffers[static_cast<uint8_t>(inputStream)] = buffer;
// Create a buffer view to use as input to the skinning shader
AZ::RHI::Ptr<AZ::RHI::BufferView> bufferView = RHI::Factory::Get().CreateBufferView();
bufferView->SetName(Name{ AZStd::string(buffer->GetBufferView()->GetName().GetStringView()) + "_SkinningInputBufferView" });
RHI::BufferViewDescriptor bufferViewDescriptor = bufferAsset->GetBufferViewDescriptor();
// 3-component float buffers are not supported on metal for non-input assembly buffer views, so use a float view instead
if (bufferViewDescriptor.m_elementFormat == RHI::Format::R32G32B32_FLOAT)
{
// Use one float per element, with 3x as many elements
bufferViewDescriptor = RHI::BufferViewDescriptor::CreateTyped(
bufferViewDescriptor.m_elementOffset * 3, bufferViewDescriptor.m_elementCount * 3, RHI::Format::R32_FLOAT);
}
[[maybe_unused]] RHI::ResultCode resultCode =
bufferView->Init(*buffer->GetRHIBuffer(), bufferViewDescriptor);
AZ_Error(
"SkinnedMeshInputBuffers", resultCode == RHI::ResultCode::Success,
"Failed to initialize buffer view for skinned mesh input.");
m_bufferViews[static_cast<uint8_t>(inputStream)] = bufferView;
}
void SkinnedMeshInputLod::SetStaticBufferAsset(const Data::Asset<RPI::BufferAsset> bufferAsset, SkinnedMeshStaticVertexStreams staticStream)
@@ -315,7 +337,7 @@ namespace AZ
[[maybe_unused]] bool success = false;
if (m_lods[lodIndex].m_inputBuffers[inputStream])
{
success = perInstanceSRG->SetBufferView(srgIndex, m_lods[lodIndex].m_inputBuffers[inputStream]->GetBufferView());
success = perInstanceSRG->SetBufferView(srgIndex, m_lods[lodIndex].m_bufferViews[inputStream].get());
}
AZ_Error("SkinnedMeshInputBuffers", success, "Failed to bind buffer view for %s", streamInfo.m_bufferName.GetCStr());