// Copyright Epic Games, Inc. All Rights Reserved. // Counts how many times each unique value of an attribute is encountered in the input data elements. // Input: Input elements with attribute. // Output: Attribute set with a ValueCount attribute which has the count of each value. Number of elements is set to the number of unique values (known CPU-side). [numthreads(64, 1, 1)] void PCGCountUniqueAttributeValuesCS(uint3 GroupId : SV_GroupID, uint GroupIndex : SV_GroupIndex) { // Mark the kernel as having executed. Must run before we early out via thread index, because the kernel is still 'executed' even if the number of // threads to iterate on is zero. Even if GetNumThreads() returns 0, the kernel will still have been dispatched on a single thread to set this flag. if (all(GroupId == 0) && GroupIndex == 0) { Out_SetAsExecutedInternal(); } const uint ThreadIndex = GetUnWrappedDispatchThreadId(GroupId, GroupIndex, 64); uint In_DataIndex, In_ElementIndex; if (!In_GetThreadData(ThreadIndex, In_DataIndex, In_ElementIndex)) { return; } if (In_IsPointRemoved(In_DataIndex, In_ElementIndex)) { return; } const int AttributeToCountId = CountUniqueValues_GetAttributeToCountId(); const int AttributeValue = In_GetStringKey(In_DataIndex, In_ElementIndex, AttributeToCountId); const uint Out_DataIndex = 0; const uint Out_ElementIndex = CountUniqueValues_GetValueIndex(AttributeValue); // Write value of attribute. const int OutputValueAttributeId = CountUniqueValues_GetOutputValueAttributeId(); Out_SetInt(Out_DataIndex, Out_ElementIndex, OutputValueAttributeId, AttributeValue); const int OutputCountAttributeId = CountUniqueValues_GetOutputCountAttributeId(); const int ValueIndex = CountUniqueValues_GetValueIndex(AttributeValue); // Increment count of this attribute. if (ValueIndex != -1) { Out_AtomicAddInt(Out_DataIndex, ValueIndex, OutputCountAttributeId, 1); } }