我试图使用Compute Shader检查光线/网格交叉点。我有一个带有Parallel.ForEach的外循环,它选择每条光线,然后对于每条光线,我使用GPU(带有计算着色器)检查交叉点。
第一个循环工作正常,但在进入第二个循环之前就崩溃了?可能是什么问题?
Parallel.ForEach(pattern, (point) => {
//foreach (Vector3 point in pattern) {
List<Vector3> pointList = new List<Vector3>();
// same ray origin and different direction for each cycle
Vector3 origin = proj.Position;
Vector3 patternPoint = new Vector3(point.X - offset + origin.X, point.Y - offset + origin.Y, origin.Z - point.Z * 0.4f);
Vector3 direction = new Vector3(patternPoint.X - origin.X, patternPoint.Y - origin.Y, patternPoint.Z - origin.Z);
Ray ray = new Ray(origin, direction);
if (D3DApp.backFlag) { proj.Projection(ray, back, pointList); }
foreach (MeshRenderer mesh in meshList) { // for all the meshes in the list
if (mesh != null) { if (ray.Intersects(mesh.box)) { proj.Projection(ray, mesh, pointList, context, device); } }
}
if (pointList.Any()) {
Vector3 temp = pointList.FirstOrDefault();
foreach (Vector3 p in pointList) { // keep only the first intersection found
if (Vector3.Distance(p, origin) < Vector3.Distance(temp, origin)) { temp = p; }
}
projectedPoints.Add(temp); // add point to projection pointcloud
}
});
这是为每条射线调用的投影方法:</ p>
public void Projection(SharpDX.Ray ray, MeshRenderer obj, List<Vector3> pointList, DeviceContext1 context, Device device) {
Vector3 intersectionPoint = Vector3.Zero;
Matrix toLocal = Matrix.Invert(obj.World);
ray.Position = Vector3.TransformCoordinate(ray.Position, toLocal);
ray.Direction = Vector3.TransformNormal(ray.Direction, toLocal);
ray.Direction.Normalize();
//List<Vector3> localPointList = new List<Vector3>();
/// PROVO IL RAY/MESH INTERSECT USANDO GLI SHADER
// V2.0
Vector3[] vertices = new Vector3[obj.Mesh.Triangles.Count * 3];
int[] indices = new int[obj.Mesh.Triangles.Count*3];
int k = 0;
foreach (Triangle triangle in obj.Mesh.Triangles) {
vertices[k] = triangle.Points[0];
vertices[k+1] = triangle.Points[1];
vertices[k+2] = triangle.Points[2];
indices[k] = triangle.Indices[0];
indices[k+1] = triangle.Indices[1];
indices[k+2] = triangle.Indices[2];
k += 3;
}
/*
* INPUT RESOURCES
*/
BufferDescription bufferDesc1 = new BufferDescription() {
BindFlags = BindFlags.ShaderResource,
Usage = ResourceUsage.Default,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.BufferStructured,
StructureByteStride = Utilities.SizeOf<Vector3>(),
SizeInBytes = Utilities.SizeOf<Vector3>() * obj.Mesh.Triangles.Count * 3
};
BufferDescription bufferDesc2 = new BufferDescription() {
BindFlags = BindFlags.ShaderResource,
Usage = ResourceUsage.Default,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.BufferStructured,
StructureByteStride = sizeof(int),
SizeInBytes = sizeof(int) * obj.Mesh.Triangles.Count * 3
};
Buffer positionBuffer = new Buffer(device, bufferDesc1);
context.UpdateSubresource(vertices, positionBuffer);
Buffer indexBuffer = new Buffer(device, bufferDesc2);
context.UpdateSubresource(indices, indexBuffer);
ShaderResourceViewDescription srvDesc = new ShaderResourceViewDescription() {
Format = SharpDX.DXGI.Format.Unknown,
Dimension = SharpDX.Direct3D.ShaderResourceViewDimension.ExtendedBuffer,
BufferEx = new ShaderResourceViewDescription.ExtendedBufferResource() { Flags = 0, FirstElement = 0, ElementCount = obj.Mesh.Triangles.Count * 3 }
};
ShaderResourceView srvPosition = new ShaderResourceView(device, positionBuffer, srvDesc);
ShaderResourceView srvIndex = new ShaderResourceView(device, indexBuffer, srvDesc);
context.ComputeShader.SetShaderResource(0, srvPosition);
context.ComputeShader.SetShaderResource(1, srvIndex);
/*
* OUTPUT RESOURCES
*/
int count = obj.Mesh.Triangles.Count;
int size = 8; //int+float for every hit
BufferDescription outputDesc = new BufferDescription() {
BindFlags = BindFlags.UnorderedAccess | BindFlags.ShaderResource,
Usage = ResourceUsage.Default,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.BufferStructured,
StructureByteStride = size,
SizeInBytes = size * count
};
Buffer buffer = new Buffer(device, outputDesc);
UnorderedAccessViewDescription uavDesc = new UnorderedAccessViewDescription() {
Buffer = new UnorderedAccessViewDescription.BufferResource() { FirstElement = 0, Flags = UnorderedAccessViewBufferFlags.None, ElementCount = count },
Format = SharpDX.DXGI.Format.Unknown,
Dimension = UnorderedAccessViewDimension.Buffer
};
UnorderedAccessView uav = new UnorderedAccessView(device, buffer, uavDesc);
context.ComputeShader.SetUnorderedAccessView(0, uav);
/*
* COMPUTE SHADER
*/
var computeBuffer = new Buffer(device, Utilities.SizeOf<ConstantBuffers.RayParams>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
var rayBuffer = new ConstantBuffers.RayParams {
rayFrom = ray.Position,
rayDir = ray.Direction,
TriangleCount = (uint)obj.Mesh.Triangles.Count
};
context.UpdateSubresource(ref rayBuffer, computeBuffer);
context.ComputeShader.SetConstantBuffer(0, computeBuffer);
var code = HLSLCompiler.CompileFromFile(@"Shaders\TestTriangle.hlsl", "CS_RayAppend", "cs_5_0");
ComputeShader _shader = new ComputeShader(device, code);
context.ComputeShader.Set(_shader);
context.Dispatch(1,1,1);
//Buffer positionsBuffer = new Buffer(device, Utilities.SizeOf<Vector3>(), ResourceUsage.Default, BindFlags.None, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
//context.UpdateSubresource(ref data, positionsBuffer);
BufferDescription bufferDesc = new BufferDescription() {
SizeInBytes = size,
BindFlags = BindFlags.None,
CpuAccessFlags = CpuAccessFlags.Read | CpuAccessFlags.Write,
Usage = ResourceUsage.Staging,
OptionFlags = ResourceOptionFlags.None,
};
Buffer resultBuffer = new Buffer(device, bufferDesc);
context.CopyResource(buffer, resultBuffer);
context.Flush();
context.ComputeShader.SetShaderResource(0, null);
context.ComputeShader.SetShaderResource(1, null);
context.ComputeShader.SetConstantBuffer(0, null);
context.ComputeShader.SetUnorderedAccessView(0, null);
context.ComputeShader.Set(null);
DataStream stream;
context.MapSubresource(resultBuffer, 0, MapMode.Read, MapFlags.None, out stream);
Vector3[] result = stream.ReadRange<Vector3>(count);
context.UnmapSubresource(buffer, 0);
List<Vector3> localPointList = new List<Vector3>(result);
foreach (Vector3 point in localPointList) {
// inverted transform to retrieve the original coordinates
pointList.Add(Vector3.TransformCoordinate(point, obj.World));
}
}