Quantcast
Channel: Questions in topic: "compute shader"
Viewing all articles
Browse latest Browse all 287

Odd behaviour when retrieving data from compute shader

$
0
0
I've started converting my multithreaded planetary generation code to a compute shader, but I've ran into a weird issue I can't seem to figure out. Here is all the code in question first: private void ConstructMeshGPU() { Vector3[] verticesArray = new Vector3[vertices]; int[] trianglesArray = new int[triangles]; ComputeBuffer verticesBuffer = new ComputeBuffer(vertices, sizeof(float) * 3); verticesBuffer.SetData(verticesArray); ComputeBuffer trianglesBuffer = new ComputeBuffer(triangles, sizeof(int)); trianglesBuffer.SetData(trianglesArray); Vector2[] uvsArray = new Vector2[vertices]; ComputeBuffer uvsBuffer = new ComputeBuffer(vertices, sizeof(float) * 2); uvsBuffer.SetData(uvsArray); ComputeBuffer chunkDataBuffer = new ComputeBuffer(chunkData.Count, sizeof(int) * 3 + sizeof(float) * 2 + sizeof(float) * 6); chunkDataBuffer.SetData(chunkData.ToArray()); int[] verticesPerMeshMin = new int[verticesPerMesh.Count]; int[] verticesPerMeshMax = new int[verticesPerMesh.Count]; int[][] verticesPerMeshArray = verticesPerMesh.ToArray(); for(int i = 0; i < verticesPerMesh.Count; i++) { verticesPerMeshMin[i] = verticesPerMeshArray[i][0]; verticesPerMeshMax[i] = verticesPerMeshArray[i][1]; //Debug.Log(verticesPerMeshMin[i]); } int[] trianglesPerMeshMin = new int[trianglesPerMesh.Count]; int[] trianglesPerMeshMax = new int[trianglesPerMesh.Count]; int[][] trianglesPerMeshArray = trianglesPerMesh.ToArray(); for(int i = 0; i < trianglesPerMesh.Count; i++) { trianglesPerMeshMin[i] = trianglesPerMeshArray[i][0]; trianglesPerMeshMax[i] = trianglesPerMeshArray[i][1]; } ComputeBuffer verticesPerMeshMinBuffer = new ComputeBuffer(verticesPerMesh.Count, sizeof(int)); verticesPerMeshMinBuffer.SetData(verticesPerMeshMin); ComputeBuffer trianglesPerMeshMinBuffer = new ComputeBuffer(trianglesPerMesh.Count, sizeof(int)); trianglesPerMeshMinBuffer.SetData(trianglesPerMeshMin); /*ComputeBuffer verticesPerMeshMaxBuffer = new ComputeBuffer(verticesPerMesh.Count, sizeof(int)); verticesPerMeshMinBuffer.SetData(verticesPerMeshMax); ComputeBuffer trianglesPerMeshMaxBuffer = new ComputeBuffer(trianglesPerMesh.Count, sizeof(int)); trianglesPerMeshMinBuffer.SetData(trianglesPerMeshMax);*/ terrainGenerationShader.SetBuffer(0, "vertices", verticesBuffer); terrainGenerationShader.SetBuffer(0, "triangles", trianglesBuffer); terrainGenerationShader.SetBuffer(0, "chunkData", chunkDataBuffer); terrainGenerationShader.SetBuffer(0, "uvs", uvsBuffer); terrainGenerationShader.SetBuffer(0, "verticesPerMeshMin", verticesPerMeshMinBuffer); terrainGenerationShader.SetBuffer(0, "trianglesPerMeshMin", trianglesPerMeshMinBuffer); //terrainGenerationShader.SetBuffer(0, "verticesPerMeshMax", verticesPerMeshMaxBuffer); //terrainGenerationShader.SetBuffer(0, "trianglesPerMeshMax", trianglesPerMeshMaxBuffer); //Get the thread groups if needed //terrainGenerationShader.GetKernelThreadGroupSizes(0, out uint x, out uint y, out uint z); terrainGenerationShader.Dispatch(0, Mathf.CeilToInt((float)chunkData.Count/128.0f), 1, 1); verticesBuffer.GetData(verticesArray); trianglesBuffer.GetData(trianglesArray); uvsBuffer.GetData(uvsArray); for (int i = 0; i < generators.Count; i++) { int vertCount = verticesPerMesh[i][1] - verticesPerMesh[i][0]; int triCount = trianglesPerMesh[i][1] - trianglesPerMesh[i][0]; int spawnObjCount = spawnObjectPerMesh[i][1] - spawnObjectPerMesh[i][0]; //Debug.Log(vertCount); Vector3[] _vertices = new Vector3[vertCount]; Vector2[] _uvs = new Vector2[vertCount]; int[] _triangles = new int[trianglesPerMesh[i][1] - trianglesPerMesh[i][0]]; Array.Copy(verticesArray, verticesPerMesh[i][0], _vertices, 0, vertCount); Array.Copy(uvsArray, verticesPerMesh[i][0], _uvs, 0, vertCount); Array.Copy(trianglesArray, trianglesPerMesh[i][0], _triangles, 0, triCount); generators[i].UpdateMesh(_vertices, _triangles, _vertices, _uvs,/* _vertDistances,*/ 75, 100); //generators[i].SpawnObjects(_spawnObjectLocalPositions, _spawnObjectVectorUp, _spawnObjectRotation, _spawnObjectScales, _spawnObjectIndex); } verticesBuffer.Release(); trianglesBuffer.Release(); uvsBuffer.Release(); chunkDataBuffer.Release(); verticesPerMeshMinBuffer.Release(); trianglesPerMeshMinBuffer.Release(); //verticesPerMeshMaxBuffer.Dispose(); //trianglesPerMeshMaxBuffer.Dispose(); } And here is the compute shader: #pragma kernel CSMain struct ChunkData { int lod; float3 position; float3 center; int gridSize; float scale; float radius; int side; }; RWStructuredBuffer vertices; RWStructuredBuffer triangles; RWStructuredBuffer uvs; RWStructuredBuffer chunkData; RWStructuredBuffer verticesPerMeshMin; RWStructuredBuffer trianglesPerMeshMin; //RWStructuredBuffer verticesPerMeshMax; //RWStructuredBuffer trianglesPerMeshMax; [numthreads(128,1,1)] void CSMain (uint3 id : SV_DispatchThreadID) { ChunkData _chunkData = chunkData[id.x]; //_minDistance[index] = float.MaxValue; //_maxDistance[index] = float.MinValue; float addToCenter = 0.5f * _chunkData.scale; for (int i = verticesPerMeshMin[id.x], z = - 1; z < _chunkData.gridSize; z++) { for (int x = - 1; x < _chunkData.gridSize; x++, i++) { //vertices[i] = float3(1.0f, 1.0f, 1.0f); float xPos = ((float)x / (float)(_chunkData.gridSize - 2)) * _chunkData.scale - addToCenter; float zPos = ((float)z / (float)(_chunkData.gridSize - 2)) * _chunkData.scale - addToCenter; vertices[i] = float3(xPos , _chunkData.radius / 2, zPos); uvs[i] = /*float2(1.0f, 1.0f);*/float2((float)(x + 1) / (float)(_chunkData.gridSize - 2), (float)(z + 1) / (float)(_chunkData.gridSize - 2)); vertices[i] = normalize(vertices[i] - _chunkData.center) * (_chunkData.radius / 2) + _chunkData.center; } } int tris = 0; int vert = 2 + _chunkData.gridSize; for (int z = 0; z < _chunkData.gridSize - 2; z++) { for (int x = 0; x < _chunkData.gridSize - 2; x++) { triangles[trianglesPerMeshMin[id.x] + tris + 0] = vert; triangles[trianglesPerMeshMin[id.x] + tris + 1] = vert + _chunkData.gridSize + 1; triangles[trianglesPerMeshMin[id.x] + tris + 2] = vert + 1; triangles[trianglesPerMeshMin[id.x] + tris + 3] = vert + 1; triangles[trianglesPerMeshMin[id.x] + tris + 4] = vert + _chunkData.gridSize + 1; triangles[trianglesPerMeshMin[id.x] + tris + 5] = vert + _chunkData.gridSize + 2; tris += 6; vert++; } vert +=3; } } As to explain how the code in question works - there is a master array of all vertices ( same goes for triangles, but I'll focus on vertices since if we fix the vertices the triangles will be fixed as well ) that need to be generated for all chunks. There is another array that pinpoints where the vertices for each chunk begin, that is how I distribute them to all chunks after the fact. I had simplified the compute shader before as a part of testing, and I can confirm that there is nothing wrong with the vertex and triangle calculation, the shader just seems to spit out wrong data for all the vertices related to the very first chunk in the array. Whatever chunk is first in the array (same goes if the array only has one chunk to be generated) will have all the vertex positions set to (0,0,0) , say for one of them which can either get the 000 output, the correct output or just NaN. All the vertices in the array that are not related to that first chunk get generated without issues. I've checked all the inputs multiple times now, there is no issue with the data I'm sending to the compute shader as far as I can tell.

Viewing all articles
Browse latest Browse all 287

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>