private void FinishBakeJob() { var pixels = _currentBakeJob.Finish(); int pixelCount = _currentBakeJob.Resolution * _currentBakeJob.Resolution; var arraySize = 4 * 3 * pixelCount; arraySize += 4 * 4; var builder = new FlatBufferBuilder(arraySize); WorkloadComplete.StartResultsVector(builder, pixelCount); foreach (var color in pixels) { Vec3.CreateVec3(builder, color.r, color.g, color.b); } var resultsVectorOffset = builder.EndVector(); WorkloadComplete.StartWorkloadComplete(builder); WorkloadComplete.AddResults(builder, resultsVectorOffset); WorkloadComplete.AddWorkloadID(builder, _currentBakeJob.JobID); var messageDataOffset = WorkloadComplete.EndWorkloadComplete(builder); Message.StartMessage(builder); Message.AddData(builder, messageDataOffset.Value); Message.AddDataType(builder, MessageDatum.WorkloadComplete); var messageOffset = Message.EndMessage(builder); builder.Finish(messageOffset.Value); var byteArray = builder.SizedByteArray(); _currentBakeJob = null; _outgoingMessages.Enqueue(byteArray); }
private void ProcessNewMessages() { while (_incommingMessages.TryDequeue(out Message message)) { switch (message.DataType) { case MessageDatum.WorkloadRequest: ProcessWorkloadRequest(message); break; case MessageDatum.CancelWorkload: ProcessCancelWorkload(message); break; case MessageDatum.ShutdownMessage: if (_currentBakeJob != null) { _currentBakeJob.CancelJob(); } this._cancleQueue.Clear(); this._currentBakeJob = null; while (_incommingMessages.Count > 0) { _incommingMessages.TryDequeue(out Message messageT); } _jobIDs.Clear(); _jobs.Clear(); _isShuttingDown = true; break; } } }
private BakeJob FilloutBakeJob(WorkloadRequest workloadRequest) { var bakeJob = new BakeJob(); bakeJob.Processor = this; bakeJob.BounceCount = workloadRequest.BounceCount; bakeJob.JobID = workloadRequest.WorkloadID; bakeJob.ComputeShader = ComputeShader; var vec3 = workloadRequest.LightSourceForwardDir.Value; bakeJob.LightSourceForward = new Vector4(vec3.X, vec3.Y, vec3.Z, 0.0f); vec3 = workloadRequest.LightSourceUpwardDir.Value; bakeJob.LightSourceUpward = new Vector4(vec3.X, vec3.Y, vec3.Z, 0.0f); var vector3 = Vector3.Cross(bakeJob.LightSourceUpward, bakeJob.LightSourceForward); bakeJob.LightSourceRightward = new Vector4(vector3.x, vector3.y, vector3.z, 0.0f); vec3 = workloadRequest.LightSourcePosition.Value; bakeJob.LightSourcePosition = new Vector4(vec3.X, vec3.Y, vec3.Z, 1.0f); bakeJob.LightSourceTheta = workloadRequest.LightSourceThetaRads; bakeJob.MaxRange = workloadRequest.MaxRange; bakeJob.MinRange = workloadRequest.MinRange; bakeJob.Resolution = workloadRequest.Resolution; bakeJob.SampleCount = workloadRequest.SampleCount; bakeJob.ShadowFocusPlane = workloadRequest.ShadowFocusPlane; bakeJob.Indices = workloadRequest.GetIndicesArray(); var arraySize = workloadRequest.VerticesLength; bakeJob.Vertices = new Vector3[arraySize]; for (int i = 0; i < arraySize; i++) { vec3 = workloadRequest.Vertices(i).Value; bakeJob.Vertices[i] = new Vector3(vec3.X, vec3.Y, vec3.Z); } arraySize = workloadRequest.ObjectDataLength; bakeJob.ObjectData = new ObjectMeshDatum[arraySize]; for (int i = 0; i < arraySize; i++) { var ipc = workloadRequest.ObjectData(i).Value; var objectDatum = new ObjectMeshDatum(); objectDatum.IndicesCount = ipc.IndicesCount; objectDatum.IndicesOffset = ipc.IndicesOffset; objectDatum.VerticesOffset = ipc.VerticesOffset; objectDatum.BoundingBox = new AABB_Bounds(); var ipcBounds = ipc.Bounds; vec3 = ipcBounds.Center; objectDatum.BoundingBox.Center = new Vector3(vec3.X, vec3.Y, vec3.Z); vec3 = ipcBounds.Extent; objectDatum.BoundingBox.Extent = new Vector3(vec3.X, vec3.Y, vec3.Z); var ipcLTWM = ipc.LocalToWorldMatrix; objectDatum.LocalToWorldMatrix = new UnityEngine.Matrix4x4(); objectDatum.LocalToWorldMatrix.SetRow(0, new Vector4(ipcLTWM.M00, ipcLTWM.M01, ipcLTWM.M02, ipcLTWM.M03)); objectDatum.LocalToWorldMatrix.SetRow(1, new Vector4(ipcLTWM.M10, ipcLTWM.M11, ipcLTWM.M12, ipcLTWM.M13)); objectDatum.LocalToWorldMatrix.SetRow(2, new Vector4(ipcLTWM.M20, ipcLTWM.M21, ipcLTWM.M22, ipcLTWM.M23)); objectDatum.LocalToWorldMatrix.SetRow(3, new Vector4(ipcLTWM.M30, ipcLTWM.M31, ipcLTWM.M32, ipcLTWM.M33)); bakeJob.ObjectData[i] = objectDatum; } return(bakeJob); }
private void Update() { if (_isShuttingDown) { if (_udpBackgoundMessenger.IsBusy) { return; } else { Application.Quit(0); } } // Process any new messages that came in since the last update ProcessNewMessages(); // Remove any jobs that have been canceled from the job queue. RemoveCanceledJobsFromQueue(); // If there's a job currently running and it has been canceled, then cancel it if (_currentBakeJob != null) { if (_cancleQueue.Contains(_currentBakeJob.JobID)) { _currentBakeJob.CancelJob(); _currentBakeJob = null; } } /// /// Note: The if/else-if statement is there to stop me from starting a new job and running it's first update /// within the same frame. Other than that, there is no reason for using an if/else-if. I could use two /// if states and run a job's first update in the same frame as that job's start() call. /// // If there are no jobs running, and we have jobs queued up, then start the next job in the queue if (_currentBakeJob == null && _jobs.Count > 0) { _currentBakeJob = _jobs.Dequeue(); _currentBakeJob.StartJob(); } // If there's a job running else if (_currentBakeJob != null) { // If the job is complete if (_currentBakeJob.JobComplete) { FinishBakeJob(); } else { _currentBakeJob.Update(); } } // One thing I learned when dealing with systems with lots of memory is that you should run the garbage // collector from time to time when you are generating lots of items on the heap. The reason for this // is because there's a chance that the GC won't runt until you fill up on lots of un-recovered memory; // in a system with lots of memory, reclaiming a large heap can cause the process to pause long enough // for it to crash. I will repeat, reclaiming a large enough heap can cause the process to pause long // enough to cause it to crash. I think it has something to do with some Graphics APIs throwing up an // error when they drop below a certain FPS. It might also be a Windows thing, I know for a fact that // it doesn't like it when a windows' FPS drops well below 1. I learned this the hard way when I was // doing image capturing for some NN training on some server-hardware. The image capture was done on // server grade hardware; I've don't now which hardware the training was done on because I wasn't // working that part of the project. Anyways, each frame created a new byte array that would get saved // to disk, and those arrays just built-up inside the heap. A few hours in, the memory use had grown // well over 100 GB and the GC was triggered. That GC clean-up took so long that process crashed. So, I // throw in a CG call every couple of frames and ran the process for an 8 hour batch at a higher // resoultion than needed, to really make sure the problem was fixed. Now you know why I'm running a // call to the GC every 'X' frames on a process that's expected to create quite a few byte arrays that // aren't all needed at once. And, no, I wasn't able to put those byte arrays inside of a memory pool, // the item that generated them isn't part of the code that I wrote, and it didn't have a method for // incoding to a given array. // -FCT _updatesSinceLastGC++; if (_updatesSinceLastGC % 10 == 0) { System.GC.Collect(); _updatesSinceLastGC = 0; } }