/// <summary> /// This function takes vertices from the source buffer and moves them by /// descent vector times stepLength (Pk*stepLength). /// Then it writes them into the destination buffer with new positions. /// This function does not change data in the source buffer. /// </summary> /// <param name="device"></param> /// <param name="srcVertexBuffer"></param> /// <param name="dstVertexBuffer"></param> /// <param name="parameters"></param> public void MoveVertices(StructuredBuffer srcVertexBuffer, StructuredBuffer dstVertexBuffer, ComputeParams parameters) { parameters.MaxParticles = (uint)ParticleCount; paramsCB.SetData(parameters); device.ComputeShaderConstants[0] = paramsCB; device.ComputeShaderResources[0] = srcVertexBuffer; device.SetCSRWBuffer(0, dstVertexBuffer, (int)parameters.MaxParticles); device.PipelineState = factory[(int)(ComputeFlags.COMPUTE | ComputeFlags.MOVE)]; device.Dispatch(MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)); device.ResetStates(); }
/// <summary> /// This function calculates two values: /// 1. Energy E for every vertex (N floats) /// 2. Descent vector which equals -grad(E) (3*N floats) /// Values are overwritten into the same buffer /// </summary> /// <param name="device"></param> /// <param name="rwVertexBuffer"></param> /// <param name="parameters"></param> public void CalcDescentVector(StructuredBuffer rwVertexBuffer, ComputeParams parameters) { parameters.MaxParticles = (uint)ParticleCount; paramsCB.SetData(parameters); device.ComputeShaderConstants[0] = paramsCB; device.SetCSRWBuffer(0, rwVertexBuffer, (int)parameters.MaxParticles); device.ComputeShaderResources[2] = LinksIndexBuffer; device.ComputeShaderResources[3] = LinksBuffer; device.ComputeShaderResources[4] = SelectBuffer; device.PipelineState = factory[(int)( ComputeFlags.COMPUTE | ComputeFlags.SIMULATION | ComputeFlags.EULER | ComputeFlags.LINKS)]; // device.PipelineState = factory[(int)( // ComputeFlags.COMPUTE | ComputeFlags.SIMULATION | // ComputeFlags.EULER)]; device.Dispatch(MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)); // device.ResetStates(); // add localization forces: device.PipelineState = factory[(int)(ComputeFlags.COMPUTE | ComputeFlags.LOCAL)]; if (categories.Count > 0) { foreach (var cat in categories) { parameters.LocalCenter = new Vector4(cat.Center, 0); parameters.LocalRadius = cat.Radius; parameters.StartIndex = cat.startIndex; parameters.EndIndex = cat.endIndex; paramsCB.SetData(parameters); // device.ComputeShaderConstants[0] = paramsCB; device.Dispatch(MathUtil.IntDivUp((int)(cat.endIndex - cat.startIndex), BlockSize)); } } device.ResetStates(); }
/// <summary> /// This function calculates the following values: /// 1. Total energy at (k+1)th iteration (from nextStateBuffer). /// 2. Dot product of kth descent vector and (k+1)th energy gradient (which equals minus (k+1)th descent vector) /// </summary> /// <param name="device"></param> /// <param name="currentStateBuffer"></param> /// <param name="nextStateBuffer"></param> /// <param name="outputValues"></param> /// <param name="parameters"></param> /// <param name="energy"></param> /// <param name="pTgradE"></param> public void CalcTotalEnergyAndDotProduct(StructuredBuffer currentStateBuffer, StructuredBuffer nextStateBuffer, StructuredBuffer outputValues, ComputeParams parameters, out float energy, out float pTgradE, out float checkSum) { parameters.MaxParticles = (uint)ParticleCount; energy = 0; pTgradE = 0; checkSum = 0; if (UseGPU) { // preform reduction on GPU: paramsCB.SetData(parameters); device.ComputeShaderConstants[0] = paramsCB; device.ComputeShaderResources[0] = currentStateBuffer; device.ComputeShaderResources[1] = nextStateBuffer; device.SetCSRWBuffer(1, outputValues, MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)); device.PipelineState = factory[(int)ComputeFlags.COMPUTE | (int)ComputeFlags.REDUCTION]; device.Dispatch(MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)); // perform final summation: Vector4[] valueBufferCPU = new Vector4[MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)]; outputValues.GetData(valueBufferCPU); foreach (var value in valueBufferCPU) { energy += value.X; pTgradE += value.Y; checkSum += value.Z; } } else // if not use GPU { // perform summation on CPU: Particle3d[] currentBufferCPU = new Particle3d[parameters.MaxParticles]; Particle3d[] nextBufferCPU = new Particle3d[parameters.MaxParticles]; currentStateBuffer.GetData(currentBufferCPU); nextStateBuffer.GetData(nextBufferCPU); for (int i = 0; i < parameters.MaxParticles; ++i) { Vector3 force1 = currentBufferCPU[i].Force; Vector3 force2 = nextBufferCPU[i].Force; pTgradE += -1.0f * Vector3.Dot(force1, force2); energy += nextBufferCPU[i].Energy; checkSum += nextBufferCPU[i].Mass; } } energy /= 2; // because each pair is counted 2 times }
/// <summary> /// This function takes vertices from the source buffer and moves them by /// descent vector times stepLength (Pk*stepLength). /// Then it writes them into the destination buffer with new positions. /// This function does not change data in the source buffer. /// </summary> /// <param name="device"></param> /// <param name="srcVertexBuffer"></param> /// <param name="dstVertexBuffer"></param> /// <param name="parameters"></param> public void MoveVertices(StructuredBuffer srcVertexBuffer, StructuredBuffer dstVertexBuffer, ComputeParams parameters) { parameters.MaxParticles = (uint)ParticleCount; paramsCB.SetData(parameters); device.ComputeShaderConstants[0] = paramsCB; device.ComputeShaderResources[0] = srcVertexBuffer; device.SetCSRWBuffer(0, dstVertexBuffer, (int)parameters.MaxParticles); device.PipelineState = factory[(int)(ComputeFlags.COMPUTE | ComputeFlags.MOVE)]; device.Dispatch(MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)); device.ResetStates(); }
/// <summary> /// This function calculates the following values: /// 1. Total energy at (k+1)th iteration (from nextStateBuffer). /// 2. Dot product of kth descent vector and (k+1)th energy gradient (which equals minus (k+1)th descent vector) /// </summary> /// <param name="device"></param> /// <param name="currentStateBuffer"></param> /// <param name="nextStateBuffer"></param> /// <param name="outputValues"></param> /// <param name="parameters"></param> /// <param name="energy"></param> /// <param name="pTgradE"></param> public void CalcTotalEnergyAndDotProduct(StructuredBuffer currentStateBuffer, StructuredBuffer nextStateBuffer, StructuredBuffer outputValues, ComputeParams parameters, out float energy, out float pTgradE, out float checkSum) { parameters.MaxParticles = (uint)ParticleCount; energy = 0; pTgradE = 0; checkSum = 0; if (UseGPU) { // preform reduction on GPU: paramsCB.SetData(parameters); device.ComputeShaderConstants[0] = paramsCB; device.ComputeShaderResources[0] = currentStateBuffer; device.ComputeShaderResources[1] = nextStateBuffer; device.SetCSRWBuffer(1, outputValues, MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)); device.PipelineState = factory[(int)ComputeFlags.COMPUTE | (int)ComputeFlags.REDUCTION]; device.Dispatch(MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)); // perform final summation: Vector4[] valueBufferCPU = new Vector4[MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)]; outputValues.GetData(valueBufferCPU); foreach (var value in valueBufferCPU) { energy += value.X; pTgradE += value.Y; checkSum += value.Z; } } else // if not use GPU { // perform summation on CPU: Particle3d[] currentBufferCPU = new Particle3d[parameters.MaxParticles]; Particle3d[] nextBufferCPU = new Particle3d[parameters.MaxParticles]; currentStateBuffer.GetData(currentBufferCPU); nextStateBuffer.GetData(nextBufferCPU); for (int i = 0; i < parameters.MaxParticles; ++i) { Vector3 force1 = currentBufferCPU[i].Force; Vector3 force2 = nextBufferCPU[i].Force; pTgradE += -1.0f * Vector3.Dot(force1, force2); energy += nextBufferCPU[i].Energy; checkSum += nextBufferCPU[i].Mass; } } energy /= 2; // because each pair is counted 2 times }
/// <summary> /// This function calculates two values: /// 1. Energy E for every vertex (N floats) /// 2. Descent vector which equals -grad(E) (3*N floats) /// Values are overwritten into the same buffer /// </summary> /// <param name="device"></param> /// <param name="rwVertexBuffer"></param> /// <param name="parameters"></param> public void CalcDescentVector(StructuredBuffer rwVertexBuffer, ComputeParams parameters) { parameters.MaxParticles = (uint)ParticleCount; paramsCB.SetData(parameters); device.ComputeShaderConstants[0] = paramsCB; device.SetCSRWBuffer(0, rwVertexBuffer, (int)parameters.MaxParticles); device.ComputeShaderResources[2] = LinksIndexBuffer; device.ComputeShaderResources[3] = LinksBuffer; device.ComputeShaderResources[4] = SelectBuffer; device.PipelineState = factory[(int)( ComputeFlags.COMPUTE | ComputeFlags.SIMULATION | ComputeFlags.EULER | ComputeFlags.LINKS)]; // device.PipelineState = factory[(int)( // ComputeFlags.COMPUTE | ComputeFlags.SIMULATION | // ComputeFlags.EULER)]; device.Dispatch(MathUtil.IntDivUp((int)parameters.MaxParticles, BlockSize)); // device.ResetStates(); // add localization forces: device.PipelineState = factory[(int)(ComputeFlags.COMPUTE | ComputeFlags.LOCAL)]; if (categories.Count > 0) { foreach (var cat in categories) { parameters.LocalCenter = new Vector4(cat.Center, 0); parameters.LocalRadius = cat.Radius; parameters.StartIndex = cat.startIndex; parameters.EndIndex = cat.endIndex; paramsCB.SetData(parameters); // device.ComputeShaderConstants[0] = paramsCB; device.Dispatch(MathUtil.IntDivUp((int)(cat.endIndex - cat.startIndex), BlockSize)); } } device.ResetStates(); }