using Unity.Mathematics;
namespace UnityEngine.Rendering.UnifiedRayTracing
{
internal static class GraphicsHelpers
{
static public void CopyBuffer(ComputeShader copyShader, CommandBuffer cmd, GraphicsBuffer src, int srcOffsetInDWords, GraphicsBuffer dst, int dstOffsetInDwords, int sizeInDWords)
{
const int groupSize = 256;
const int elementsPerThread = 8;
const int maxThreadGroups = 65535; // gfx device limitation
const int maxBatchSizeInDWords = groupSize * elementsPerThread * maxThreadGroups;
int remainingDWords = sizeInDWords;
cmd.SetComputeBufferParam(copyShader, 0, "_SrcBuffer", src);
cmd.SetComputeBufferParam(copyShader, 0, "_DstBuffer", dst);
while (remainingDWords > 0)
{
int batchSize = math.min(remainingDWords, maxBatchSizeInDWords);
cmd.SetComputeIntParam(copyShader, "_SrcOffset", srcOffsetInDWords);
cmd.SetComputeIntParam(copyShader, "_DstOffset", dstOffsetInDwords);
cmd.SetComputeIntParam(copyShader, "_Size", batchSize);
cmd.DispatchCompute(copyShader, 0, DivUp(batchSize, elementsPerThread * groupSize), 1, 1);
remainingDWords -= batchSize;
srcOffsetInDWords += batchSize;
dstOffsetInDwords += batchSize;
}
}
static public void CopyBuffer(ComputeShader copyShader, GraphicsBuffer src, int srcOffsetInDWords, GraphicsBuffer dst, int dstOffsetInDwords, int sizeInDwords)
{
CommandBuffer cmd = new CommandBuffer();
CopyBuffer(copyShader, cmd, src, srcOffsetInDWords, dst, dstOffsetInDwords, sizeInDwords);
Graphics.ExecuteCommandBuffer(cmd);
}
static public int DivUp(int x, int y) => (x + y - 1) / y;
static public int DivUp(int x, uint y) => (x + (int)y - 1) / (int)y;
static public uint DivUp(uint x, uint y) => (x + y - 1) / y;
static public uint3 DivUp(uint3 x, uint3 y) => (x + y - 1) / y;
///
/// Immediately executes the pending work on the command buffer.
/// This is useful for preventing TDR, which can happen when scheduling too much work in one CommandBuffer.
///
/// Command buffer to execute.
static public void Flush(CommandBuffer cmd)
{
Graphics.ExecuteCommandBuffer(cmd);
cmd.Clear();
GL.Flush();
}
}
}