Adaug proiectul Unity

This commit is contained in:
2026-11-01 23:39:55 +02:00
parent cb14d9d37d
commit 863eac8f2c
23463 changed files with 5412601 additions and 0 deletions
@@ -0,0 +1,268 @@
using System.IO;
using System.Linq;
using NUnit.Framework;
using UnityEngine.TestTools;
using UnityEngine;
using UnityEngine.Rendering;
#if UNITY_EDITOR
using UnityEditor;
#endif
#if UNITY_ANDROID
using Unity.TestUtilities;
#endif
class ThreadingEmulationFunctionTests : IPrebuildSetup
{
private const string kPathToWaveShader = "Packages/com.unity.render-pipelines.core/Tests/Runtime/Threading/FunctionTestsWave.compute";
private const string kPathToGroupShader = "Packages/com.unity.render-pipelines.core/Tests/Runtime/Threading/FunctionTestsGroup.compute";
private static int kMaxTestBlockSize = 1024;
private ComputeShader m_waveCs;
private ComputeShader m_groupCs;
private GraphicsBuffer m_inputBuffer;
private GraphicsBuffer m_outputBuffer;
private int[] m_sequenceBufferData;
private int[] m_zeroedBufferData;
public enum Kernel
{
AllEqual,
AllTrue,
AnyTrue,
Ballot,
BitAnd,
BitOr,
BitXor,
CountBits,
Max,
Min,
Product,
Sum,
GetCount,
GetIndex,
IsFirst,
PrefixCountBits,
PrefixProduct,
PrefixSum,
ReadAtBroadcast,
ReadAtShuffle,
ReadFirst,
}
public enum WaveSizeKeyword
{
EMULATE_WAVE_SIZE_8,
EMULATE_WAVE_SIZE_16,
EMULATE_WAVE_SIZE_32,
EMULATE_WAVE_SIZE_64,
EMULATE_WAVE_SIZE_128,
WAVE_SIZE_NATIVE
}
public enum GroupSizeKeyword
{
GROUP_SIZE_1 = 1,
GROUP_SIZE_2 = 2,
GROUP_SIZE_4 = 4,
GROUP_SIZE_8 = 8,
GROUP_SIZE_16 = 16,
GROUP_SIZE_32 = 32,
GROUP_SIZE_64 = 64,
GROUP_SIZE_128 = 128,
GROUP_SIZE_256 = 256,
GROUP_SIZE_512 = 512,
GROUP_SIZE_1024 = 1024
}
string GetTestResourceName(string srcPath)
{
return "_" + Path.GetFileNameWithoutExtension(srcPath);
}
#if UNITY_EDITOR
void CopyTestResource(string srcPath)
{
string dstPath = Path.Join("Assets/Resources", GetTestResourceName(srcPath) + Path.GetExtension(srcPath));
AssetDatabase.CopyAsset(srcPath, dstPath);
}
#endif
// Note: We don't currently attempt to clean up these resources because other tests could be using
// the resources folder.
public void Setup()
{
#if UNITY_EDITOR
if (!AssetDatabase.IsValidFolder("Assets/Resources"))
{
AssetDatabase.CreateFolder("Assets", "Resources");
}
CopyTestResource(kPathToWaveShader);
CopyTestResource(kPathToGroupShader);
AssetDatabase.Refresh();
#endif
}
[OneTimeSetUp]
public void OneTimeSetup()
{
if (!SystemInfo.supportsComputeShaders)
Assert.Ignore("Compute shaders are a prerequisite for the threading tests and they aren't supported on the current device");
m_waveCs = Resources.Load<ComputeShader>(GetTestResourceName(kPathToWaveShader));
Assert.IsNotNull(m_waveCs, "Failed to find threading wave test compute shader kernel");
m_groupCs = Resources.Load<ComputeShader>(GetTestResourceName(kPathToGroupShader));
Assert.IsNotNull(m_groupCs, "Failed to find threading group test compute shader kernel");
m_sequenceBufferData = Enumerable.Range(0, kMaxTestBlockSize).ToArray();
m_zeroedBufferData = Enumerable.Repeat(0, kMaxTestBlockSize).ToArray();
m_inputBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Raw, kMaxTestBlockSize, 4);
m_outputBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Raw, kMaxTestBlockSize, 4);
m_inputBuffer.SetData(m_sequenceBufferData);
}
[OneTimeTearDown]
public void OneTimeCleanUp()
{
m_inputBuffer.Release();
m_outputBuffer.Release();
}
[SetUp]
public void SetUp()
{
// Zero the output buffer before each test case
m_outputBuffer.SetData(m_zeroedBufferData);
}
private static int[] GetBufferData(GraphicsBuffer buffer)
{
int[] result = null;
var cmdReadBack = CommandBufferPool.Get("Readback");
cmdReadBack.RequestAsyncReadback(buffer, req =>
{
if (req.done)
{
var data = req.GetData<int>();
result = data.ToArray();
}
});
cmdReadBack.WaitAllAsyncReadbackRequests();
Graphics.ExecuteCommandBuffer(cmdReadBack);
CommandBufferPool.Release(cmdReadBack);
return result;
}
private void ValidateDeviceComputeGroupSize(int requiredComputeGroupSizeX)
{
int deviceMaxComputeGroupSizeX = SystemInfo.maxComputeWorkGroupSizeX;
if (deviceMaxComputeGroupSizeX < requiredComputeGroupSizeX)
Assert.Ignore($"The device's max compute group size X dimension ({deviceMaxComputeGroupSizeX}) does not meet the minimum requirement ({requiredComputeGroupSizeX}) for this test");
}
[SetUp]
public void SetupIgnores()
{
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.WebGPU)
{
Assert.Ignore("These tests are not supported on WebGPU");
}
}
[Test]
[Ignore("Unstable: https://jira.unity3d.com/browse/UUM-111743")]
public void WaveTest([Values]Kernel kernel, [Values]WaveSizeKeyword waveSizeKeyword)
{
#if UNITY_ANDROID
// ReadAtBroadcast with the native wave size returns 0 on the Samsung Galaxy S20 FE
// (Adreno 650, Vulkan). However, Quest2 is passing even though it has the same GPU,
// so it seems to be the S20 FE driver specifically, not Adreno 650 in general. Suspected
// driver/cross-compiler bug around WaveReadLaneAt with a WaveGetLaneCount()-derived
// (dynamically-uniform but not literal-constant) lane index — the shuffle variant works.
if (AndroidUtilities.AndroidDeviceId == "r8q" // r8q == Samsung Galaxy S20 FE
&& SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan
&& kernel == Kernel.ReadAtBroadcast
&& waveSizeKeyword == WaveSizeKeyword.WAVE_SIZE_NATIVE)
{
Assert.Ignore("ReadAtBroadcast/native wave broken on Adreno 650 / Samsung Galaxy S20 FE (Vulkan)");
}
#endif
int groupSize = (int)GroupSizeKeyword.GROUP_SIZE_128;
// Ensure that the wave tests are capable of running on the current device
ValidateDeviceComputeGroupSize(groupSize);
// When emulating wave sizes, a special shader keyword must be activated.
bool hasEmulatedWaveSize = waveSizeKeyword != WaveSizeKeyword.WAVE_SIZE_NATIVE;
var cmd = CommandBufferPool.Get("Threading Wave Test");
if (hasEmulatedWaveSize)
{
cmd.SetKeyword(m_waveCs, new LocalKeyword(m_waveCs, waveSizeKeyword.ToString()), true);
}
int kernelIndex = (int)kernel;
cmd.SetComputeBufferParam(m_waveCs, kernelIndex, "_Input", m_inputBuffer);
cmd.SetComputeBufferParam(m_waveCs, kernelIndex, "_Output", m_outputBuffer);
cmd.DispatchCompute(m_waveCs, kernelIndex, 1, 1, 1);
if (hasEmulatedWaveSize)
{
cmd.SetKeyword(m_waveCs, new LocalKeyword(m_waveCs, waveSizeKeyword.ToString()), false);
}
Graphics.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
// Read back and compare the results.
var result = GetBufferData(m_outputBuffer);
Assert.That(result, Has.Exactly(groupSize).EqualTo(1).And.Exactly(kMaxTestBlockSize - groupSize).EqualTo(0));
}
[Test]
[Ignore("Unstable: https://jira.unity3d.com/browse/UUM-111743")]
public void GroupTest([Values]Kernel kernel, [Values]GroupSizeKeyword groupSizeKeyword)
{
int groupSize = (int)groupSizeKeyword;
// Ensure that the group tests are capable of running on the current device
ValidateDeviceComputeGroupSize(groupSize);
var cmd = CommandBufferPool.Get("Threading Group Test");
cmd.SetKeyword(m_groupCs, new LocalKeyword(m_groupCs, groupSizeKeyword.ToString()), true);
int kernelIndex = (int)kernel;
cmd.SetComputeBufferParam(m_groupCs, kernelIndex, "_Input", m_inputBuffer);
cmd.SetComputeBufferParam(m_groupCs, kernelIndex, "_Output", m_outputBuffer);
cmd.DispatchCompute(m_groupCs, kernelIndex, 1, 1, 1);
cmd.SetKeyword(m_groupCs, new LocalKeyword(m_groupCs, groupSizeKeyword.ToString()), false);
Graphics.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
// Read back and compare the results.
var result = GetBufferData(m_outputBuffer);
Assert.That(result, Has.Exactly(groupSize).EqualTo(1).And.Exactly(kMaxTestBlockSize - groupSize).EqualTo(0));
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59c8a12d341e781489ab4c7b1815b241
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,255 @@
#pragma multi_compile GROUP_SIZE_1 GROUP_SIZE_2 GROUP_SIZE_4 GROUP_SIZE_8 GROUP_SIZE_16 GROUP_SIZE_32 GROUP_SIZE_64 GROUP_SIZE_128 GROUP_SIZE_256 GROUP_SIZE_512 GROUP_SIZE_1024
// Warning: Keep this kernel order in sync with WaveKernel enum in WaveEmulationTests.cs
#pragma kernel kAllEqual
#pragma kernel kAllTrue
#pragma kernel kAnyTrue
#pragma kernel kBallot
#pragma kernel kBitAnd
#pragma kernel kBitOr
#pragma kernel kBitXor
#pragma kernel kCountBits
#pragma kernel kMax
#pragma kernel kMin
#pragma kernel kProduct
#pragma kernel kSum
#pragma kernel kGetThreadCount
#pragma kernel kGetThreadIndex
#pragma kernel kIsFirstThread
#pragma kernel kPrefixCountBits
#pragma kernel kPrefixProduct
#pragma kernel kPrefixSum
#pragma kernel kReadThreadAtBroadcast
#pragma kernel kReadThreadAtShuffle
#pragma kernel kReadThreadFirst
// Required to define before using the threading library.
#if defined(GROUP_SIZE_1)
#define THREADING_BLOCK_SIZE 1
#elif defined(GROUP_SIZE_2)
#define THREADING_BLOCK_SIZE 2
#elif defined(GROUP_SIZE_4)
#define THREADING_BLOCK_SIZE 4
#elif defined(GROUP_SIZE_8)
#define THREADING_BLOCK_SIZE 8
#elif defined(GROUP_SIZE_16)
#define THREADING_BLOCK_SIZE 16
#elif defined(GROUP_SIZE_32)
#define THREADING_BLOCK_SIZE 32
#elif defined(GROUP_SIZE_64)
#define THREADING_BLOCK_SIZE 64
#elif defined(GROUP_SIZE_128)
#define THREADING_BLOCK_SIZE 128
#elif defined(GROUP_SIZE_256)
#define THREADING_BLOCK_SIZE 256
#elif defined(GROUP_SIZE_512)
#define THREADING_BLOCK_SIZE 512
#elif defined(GROUP_SIZE_1024)
#define THREADING_BLOCK_SIZE 1024
#endif
#define THREADING_FORCE_WAVE_EMULATION
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Threading.hlsl"
typedef Threading::Group Group;
typedef Threading::GroupBallot GroupBallot;
ByteAddressBuffer _Input;
RWByteAddressBuffer _Output;
// Macros
#define DATA ((uint)_Input.Load(group.dispatchID.x << 2))
#define OUTPUT_ADDR ((uint)(group.groupIndex << 2))
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kAllEqual(Group group)
{
const uint result = (uint)group.AllEqual(DATA - group.groupIndex);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kAllTrue(Group group)
{
const uint result = (uint)group.AllTrue(DATA == group.groupIndex);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kAnyTrue(Group group)
{
const uint result = (uint)group.AnyTrue((DATA & (group.GetThreadCount() - 1)) == (group.GetThreadCount() / 2));
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kBallot(Group group)
{
GroupBallot ballot = group.Ballot(DATA == group.groupIndex);
uint numBits = ballot.CountBits();
const uint result = (numBits == group.GetThreadCount());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kBitAnd(Group group)
{
const uint result = group.And(DATA == group.groupIndex);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kBitOr(Group group)
{
const uint result = (group.Or(DATA != group.groupIndex) == 0);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kBitXor(Group group)
{
const uint result = (group.Xor(DATA != group.groupIndex) == 0);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kCountBits(Group group)
{
const uint result = (group.CountBits(DATA == group.groupIndex) == group.GetThreadCount());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kMax(Group group)
{
const uint result = (group.Max(DATA & (group.GetThreadCount() - 1)) == (group.GetThreadCount() - 1));
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kMin(Group group)
{
const uint result = (group.Min(DATA & (group.GetThreadCount() - 1)) == 0);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kProduct(Group group)
{
const uint result = group.Product((uint)(DATA == group.groupIndex));
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kSum(Group group)
{
const uint result = (group.Sum((uint)(DATA == group.groupIndex)) == group.GetThreadCount());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kGetThreadCount(Group group)
{
#if defined(THREADING_WAVE_SIZE)
const uint result = (THREADING_BLOCK_SIZE == group.GetThreadCount());
#else
// If we don't know the group size at compile time, we don't really have any way of verifying this functionality.
// Unconditionally return 1 so this case always passes.
const uint result = 1;
#endif
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kGetThreadIndex(Group group)
{
const uint result = ((DATA & (group.GetThreadCount() - 1)) == group.GetThreadIndex());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kIsFirstThread(Group group)
{
const uint result = (group.GetThreadIndex() != 0) ^ group.IsFirstThread();
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kPrefixCountBits(Group group)
{
const uint result = (group.PrefixCountBits(DATA == group.groupIndex) == group.GetThreadIndex());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kPrefixProduct(Group group)
{
const uint value = ((group.GetThreadIndex() % 64) == 0) ? 2u : 1u;
const uint expectedValue = (1u << ((group.GetThreadIndex() / 64u) + 1));
const uint result = ((group.PrefixProduct(value) * value) == expectedValue);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kPrefixSum(Group group)
{
const uint value = group.GetThreadIndex();
const uint expectedValue = (group.GetThreadIndex() * (group.GetThreadIndex() + 1u)) / 2u;
const uint result = ((group.PrefixSum(value) + value) == expectedValue);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kReadThreadAtBroadcast(Group group)
{
const uint laneValue = DATA & (group.GetThreadCount() - 1);
const uint result = (group.ReadThreadAt(laneValue, (group.GetThreadCount() - 1)) == (group.GetThreadCount() - 1));
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kReadThreadAtShuffle(Group group)
{
const uint laneValue = DATA & (group.GetThreadCount() - 1);
const uint result = (group.ReadThreadShuffle(laneValue, laneValue) == laneValue);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kReadThreadFirst(Group group)
{
const uint result = (group.ReadThreadFirst(DATA & (group.GetThreadCount() - 1)) == 0);
_Output.Store(OUTPUT_ADDR, result);
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 77f6c3e00d2daf84ba7b57e205d5dd64
ComputeShaderImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,299 @@
#pragma multi_compile _ EMULATE_WAVE_SIZE_8 EMULATE_WAVE_SIZE_16 EMULATE_WAVE_SIZE_32 EMULATE_WAVE_SIZE_64 EMULATE_WAVE_SIZE_128
#pragma multi_compile _ UNITY_DEVICE_SUPPORTS_WAVE_ANY
// Warning: Keep this kernel order in sync with Kernel enum in FunctionTests.cs
#pragma kernel kAllEqual
#pragma kernel kAllTrue
#pragma kernel kAnyTrue
#pragma kernel kBallot
#pragma kernel kBitAnd
#pragma kernel kBitOr
#pragma kernel kBitXor
#pragma kernel kCountBits
#pragma kernel kMax
#pragma kernel kMin
#pragma kernel kProduct
#pragma kernel kSum
#pragma kernel kGetLaneCount
#pragma kernel kGetLaneIndex
#pragma kernel kIsFirstLane
#pragma kernel kPrefixCountBits
#pragma kernel kPrefixProduct
#pragma kernel kPrefixSum
#pragma kernel kReadLaneAtBroadcast
#pragma kernel kReadLaneAtShuffle
#pragma kernel kReadLaneFirst
#if EMULATE_WAVE_SIZE_8
#define THREADING_WAVE_SIZE 8
#elif EMULATE_WAVE_SIZE_16
#define THREADING_WAVE_SIZE 16
#elif EMULATE_WAVE_SIZE_32
#define THREADING_WAVE_SIZE 32
#elif EMULATE_WAVE_SIZE_64
#define THREADING_WAVE_SIZE 64
#elif EMULATE_WAVE_SIZE_128
#define THREADING_WAVE_SIZE 128
#endif
// Required to define before using the threading library.
#define THREADING_BLOCK_SIZE 128
// BUG: There are currently a few issues preventing SM6 intrinsics from working on all platforms.
// For now, we avoid testing SM6 intrinsics on those platforms. Once the issues are resolved, this workaround should be removed to improve test coverage.
//
// Issues:
// 1. The BitXor, Product, and PrefixProduct SM6 intrinsics fail to compile on Xbox One because they aren't supported.
// We could potentially emulate these if necessary, but they aren't particularly useful.
// For now, we just skip the native path tests on Xbox One.
//
// 2. On some platforms, we probably cannot access SM6 instrinsics when using the HLSLcc pipeline
#define ENABLE_SM6_WORKAROUND (defined(SHADER_API_GAMECORE_XBOXONE) || defined(SHADER_API_XBOXONE) || defined(SHADER_API_SWITCH2))
// Force emulation on whenever a specific wave size is provided
#if defined(THREADING_WAVE_SIZE) || ENABLE_SM6_WORKAROUND
#define THREADING_FORCE_WAVE_EMULATION
#endif
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Threading.hlsl"
typedef Threading::Wave Wave;
typedef Threading::Group Group;
ByteAddressBuffer _Input;
RWByteAddressBuffer _Output;
// Macros
#define DATA ((uint)_Input.Load(group.dispatchID.x << 2))
#define OUTPUT_ADDR ((uint)(group.groupIndex << 2))
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kAllEqual(Group group)
{
Wave wave = group.GetWave();
const uint result = (uint)wave.AllEqual(DATA - group.groupIndex);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kAllTrue(Group group)
{
Wave wave = group.GetWave();
const uint result = (uint)wave.AllTrue(DATA == group.groupIndex);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kAnyTrue(Group group)
{
Wave wave = group.GetWave();
const uint result = (uint)wave.AnyTrue((DATA & (wave.GetLaneCount() - 1)) == (wave.GetLaneCount() / 2));
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kBallot(Group group)
{
Wave wave = group.GetWave();
uint4 ballot = wave.Ballot(DATA == group.groupIndex);
uint numBits = (countbits(ballot.x) + countbits(ballot.y) + countbits(ballot.z) + countbits(ballot.w));
const uint result = (numBits == wave.GetLaneCount());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kBitAnd(Group group)
{
Wave wave = group.GetWave();
const uint result = wave.And(DATA == group.groupIndex);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kBitOr(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.Or(DATA != group.groupIndex) == 0);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kBitXor(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.Xor(DATA != group.groupIndex) == 0);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kCountBits(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.CountBits(DATA == group.groupIndex) == wave.GetLaneCount());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kMax(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.Max(DATA & (wave.GetLaneCount() - 1)) == (wave.GetLaneCount() - 1));
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kMin(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.Min(DATA & (wave.GetLaneCount() - 1)) == 0);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kProduct(Group group)
{
Wave wave = group.GetWave();
const uint result = wave.Product((uint)(DATA == group.groupIndex));
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kSum(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.Sum((uint)(DATA == group.groupIndex)) == wave.GetLaneCount());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kGetLaneCount(Group group)
{
#if defined(THREADING_WAVE_SIZE)
Wave wave = group.GetWave();
const uint result = (THREADING_WAVE_SIZE == wave.GetLaneCount());
#else
// If we don't know the wave size at compile time, we don't really have any way of verifying this functionality.
// Unconditionally return 1 so this case always passes.
const uint result = 1;
#endif
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kGetLaneIndex(Group group)
{
Wave wave = group.GetWave();
const uint result = ((DATA & (wave.GetLaneCount() - 1)) == wave.GetLaneIndex());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kIsFirstLane(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.GetLaneIndex() != 0) ^ wave.IsFirstLane();
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kPrefixCountBits(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.PrefixCountBits(DATA == group.groupIndex) == wave.GetLaneIndex());
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kPrefixProduct(Group group)
{
Wave wave = group.GetWave();
const uint value = ((wave.GetLaneIndex() % 8) == 0) ? 2u : 1u;
const uint expectedValue = (1u << ((wave.GetLaneIndex() / 8u) + 1));
const uint result = ((wave.PrefixProduct(value) * value) == expectedValue);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kPrefixSum(Group group)
{
Wave wave = group.GetWave();
const uint value = wave.GetLaneIndex();
const uint expectedValue = (wave.GetLaneIndex() * (wave.GetLaneIndex() + 1u)) / 2u;
const uint result = ((wave.PrefixSum(value) + value) == expectedValue);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kReadLaneAtBroadcast(Group group)
{
Wave wave = group.GetWave();
const uint laneValue = DATA & (wave.GetLaneCount() - 1);
const uint result = (wave.ReadLaneAt(laneValue, (wave.GetLaneCount() - 1)) == (wave.GetLaneCount() - 1));
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kReadLaneAtShuffle(Group group)
{
Wave wave = group.GetWave();
const uint laneValue = DATA & (wave.GetLaneCount() - 1);
const uint result = (wave.ReadLaneAt(laneValue, laneValue) == laneValue);
_Output.Store(OUTPUT_ADDR, result);
}
[numthreads(THREADING_BLOCK_SIZE, 1, 1)]
void kReadLaneFirst(Group group)
{
Wave wave = group.GetWave();
const uint result = (wave.ReadLaneFirst(DATA & (wave.GetLaneCount() - 1)) == 0);
_Output.Store(OUTPUT_ADDR, result);
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7cce01e3b2c07a34b8a6cfa8dcd99d0b
ComputeShaderImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: