protected void CheckBufferChanged(GPUBufferVariable <T> source) { if (this.hashData.objectBufferSorted == null || this.hashData.objectBufferSorted.Size != source.Size) { //use source as object buffer this.hashData.objectBuffer.InitBuffer(source); //create new buffer for sorted data this.hashData.objectBufferSorted.InitBuffer(source.Size); //create new buffer for object index this.hashData.objectGridIndexBuffer.InitBuffer(source.Size); this.dispatcher = new ComputeShaderDispatcher <Kernel>(this.gridCS); foreach (Kernel k in Enum.GetValues(typeof(Kernel))) { this.dispatcher.AddParameter(k, this.gridData); this.dispatcher.AddParameter(k, this.hashData); } } else { this.hashData.objectBuffer.UpdateBuffer(source); } var gs = this.gridData.gridSize; this.hashData.hashTableSize = gs.x * gs.y * gs.z; }
public void Sort(ref GPUBufferVariable <T> source) { LogTool.LogAssertIsTrue(Mathf.IsPowerOfTwo(source.Size), "num of source should be power of 2"); LogTool.LogAssertIsTrue(source.Size >= BITONIC_BLOCK_SIZE * TRANSPOSE_BLOCK_SIZE, "source size must bigger than " + (BITONIC_BLOCK_SIZE * TRANSPOSE_BLOCK_SIZE)); if (this.tempBuffer == null || this.tempBuffer.Size != source.Size) { this.tempBuffer.InitBuffer(source.Size); } ComputeShader sortCS = this.bitonicCS; int KERNEL_ID_BITONICSORT = sortCS.FindKernel("BitonicSort"); int KERNEL_ID_TRANSPOSE = sortCS.FindKernel("MatrixTranspose"); uint NUM_ELEMENTS = (uint)source.Size; uint MATRIX_WIDTH = BITONIC_BLOCK_SIZE; uint MATRIX_HEIGHT = (uint)NUM_ELEMENTS / BITONIC_BLOCK_SIZE; for (uint level = 2; level <= BITONIC_BLOCK_SIZE; level <<= 1) { SetGPUSortConstants(sortCS, level, level, MATRIX_HEIGHT, MATRIX_WIDTH); // Sort the row data sortCS.SetBuffer(KERNEL_ID_BITONICSORT, "Data", source); sortCS.Dispatch(KERNEL_ID_BITONICSORT, (int)(NUM_ELEMENTS / BITONIC_BLOCK_SIZE), 1, 1); } // Then sort the rows and columns for the levels > than the block size // Transpose. Sort the Columns. Transpose. Sort the Rows. for (uint level = (BITONIC_BLOCK_SIZE << 1); level <= NUM_ELEMENTS; level <<= 1) { // Transpose the data from buffer 1 into buffer 2 SetGPUSortConstants(sortCS, level / BITONIC_BLOCK_SIZE, (level & ~NUM_ELEMENTS) / BITONIC_BLOCK_SIZE, MATRIX_WIDTH, MATRIX_HEIGHT); sortCS.SetBuffer(KERNEL_ID_TRANSPOSE, "Input", source); sortCS.SetBuffer(KERNEL_ID_TRANSPOSE, "Data", tempBuffer); sortCS.Dispatch(KERNEL_ID_TRANSPOSE, (int)(MATRIX_WIDTH / TRANSPOSE_BLOCK_SIZE), (int)(MATRIX_HEIGHT / TRANSPOSE_BLOCK_SIZE), 1); // Sort the transposed column data sortCS.SetBuffer(KERNEL_ID_BITONICSORT, "Data", tempBuffer); sortCS.Dispatch(KERNEL_ID_BITONICSORT, (int)(NUM_ELEMENTS / BITONIC_BLOCK_SIZE), 1, 1); // Transpose the data from buffer 2 back into buffer 1 SetGPUSortConstants(sortCS, BITONIC_BLOCK_SIZE, level, MATRIX_HEIGHT, MATRIX_WIDTH); sortCS.SetBuffer(KERNEL_ID_TRANSPOSE, "Input", tempBuffer); sortCS.SetBuffer(KERNEL_ID_TRANSPOSE, "Data", source); sortCS.Dispatch(KERNEL_ID_TRANSPOSE, (int)(MATRIX_HEIGHT / TRANSPOSE_BLOCK_SIZE), (int)(MATRIX_WIDTH / TRANSPOSE_BLOCK_SIZE), 1); // Sort the row data sortCS.SetBuffer(KERNEL_ID_BITONICSORT, "Data", source); sortCS.Dispatch(KERNEL_ID_BITONICSORT, (int)(NUM_ELEMENTS / BITONIC_BLOCK_SIZE), 1, 1); } }
public void BuildSortedParticleGridIndex(GPUBufferVariable <T> source, out GPUBufferVariable <T> sortedBuffer) { sortedBuffer = default; this.CheckBufferChanged(source); this.dispatcher.Dispatch(Kernel.BuildHash, source.Size); this.Sort.Sort(ref this.hashData.objectGridIndexBuffer); var s = this.gridData.gridSize; this.dispatcher.Dispatch(Kernel.ClearIndex, s.x, s.y, s.z); this.dispatcher.Dispatch(Kernel.BuildIndex, source.Size); this.dispatcher.Dispatch(Kernel.BuildSortedObject, source.Size); sortedBuffer = this.hashData.objectBufferSorted; }