private unsafe bool SetupComputeResources() { Debug.Assert(_gd is not null, "Init not called"); ResourceFactory factory = _gd.ResourceFactory; if (_gd.Features.ComputeShader is false) { Logging.RecordError("Error: Compute shaders are unavailable"); return(false); } byte[]? noteattribShaderBytes = ImGuiController.LoadEmbeddedShaderCode(factory, "sim-nodeAttrib", ShaderStages.Vertex); _nodeAttribShader = factory.CreateShader(new ShaderDescription(ShaderStages.Fragment, noteattribShaderBytes, "FS")); _nodeAttribComputeLayout = factory.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute), new ResourceLayoutElementDescription("nodeAttrib", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute), new ResourceLayoutElementDescription("edgeIndices", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute), new ResourceLayoutElementDescription("edgeData", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute), new ResourceLayoutElementDescription("resultData", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute))); _attribsParamsBuffer = VeldridGraphBuffers.TrackedVRAMAlloc(_gd, (uint)Unsafe.SizeOf <AttribShaderParams>(), BufferUsage.UniformBuffer, name: "AttribShaderParams"); ComputePipelineDescription attribCPL = new ComputePipelineDescription(_nodeAttribShader, _nodeAttribComputeLayout, 16, 16, 1); _nodeAttribComputePipeline = factory.CreateComputePipeline(attribCPL); return(true); }
public static unsafe Bitmap CreateRecordingFrame(Framebuffer fbuf, float startX, float startY, float drawWidth, float drawHeight) { GraphicsDevice gd = _controller !.GraphicsDevice; Texture ftex = fbuf.ColorTargets[0].Target; if (_recordingStager == null || _recordingStager.Width != ftex.Width || _recordingStager.Height != ftex.Height) { VeldridGraphBuffers.DoDispose(_recordingStager); _recordingStager = gd.ResourceFactory.CreateTexture(new TextureDescription(ftex.Width, ftex.Height, 1, 1, 1, PixelFormat.B8_G8_R8_A8_UNorm, TextureUsage.Staging, TextureType.Texture2D)); } _commandList !.Begin(); _commandList.CopyTexture(ftex, _recordingStager); _commandList.End(); gd.SubmitCommands(_commandList); gd.WaitForIdle(); if (drawWidth == -1 || drawHeight == -1) { drawHeight = _recordingStager.Height; drawWidth = _recordingStager.Width; } //draw it onto a bitmap Bitmap bmp = new Bitmap((int)drawWidth, (int)drawHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb); System.Drawing.Imaging.BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, (int)drawWidth, (int)drawHeight), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); byte *scan0 = (byte *)data.Scan0; MappedResourceView <SixLabors.ImageSharp.PixelFormats.Rgba32> res = gd.Map <SixLabors.ImageSharp.PixelFormats.Rgba32>(_recordingStager, MapMode.Read); for (int y = 0; y < drawHeight; y += 1) { for (int x = 0; x < drawWidth; x += 1) { int xPixel = (int)startX + x; int yPixel = (int)startY + y; SixLabors.ImageSharp.PixelFormats.Rgba32 px = res[xPixel, yPixel]; byte *ptr = scan0 + y * data.Stride + (x * 4); ptr[0] = px.R; ptr[1] = px.G; ptr[2] = px.B; ptr[3] = 255; } } bmp.UnlockBits(data); gd.Unmap(_recordingStager); return(bmp); }
/// <summary> /// Read out some values from a DeviceBuffer and print them to the console. Just for debugging. /// </summary> /// <param name="buf">GPU DeviceBuffer to read</param> /// <param name="message">Caption for the printout</param> /// <param name="printCount">Max values to print</param> private void DebugPrintOutputFloatBuffer(DeviceBuffer buf, string message, int printCount) { DeviceBuffer destinationReadback = VeldridGraphBuffers.GetReadback(_gd !, buf); MappedResourceView <float> destinationReadView = _gd !.Map <float>(destinationReadback, MapMode.Read); float[] outputArray = new float[destinationReadView.Count]; for (int index = 0; index < destinationReadView.Count; index++) { if (index >= destinationReadView.Count) { break; } outputArray[index] = destinationReadView[index]; } _gd.Unmap(destinationReadback); PrintFloatBufferArray(outputArray, message, printCount); VeldridGraphBuffers.VRAMDispose(destinationReadback); }
/// <summary> /// Must have read lock to call /// Find the node with the highest x/y/z dimension. Ignores w. /// </summary> /// <param name="buf">Device buffer containing values (can be speeds or positions)</param> /// <param name="nodeCount">Number of nodes to iterate over</param> /// <param name="highIndex">set to the index of the highest node</param> /// <returns></returns> private float FindHighXYZ(DeviceBuffer buf, int nodeCount, out int highIndex) { if (GlobalConfig.Settings.Logs.BulkLogging) { Logging.RecordLogEvent($"FindHighXYZ {this.EngineID}", Logging.LogFilterType.BulkDebugLogFile); } DeviceBuffer destinationReadback = VeldridGraphBuffers.GetReadback(_gd !, buf); MappedResourceView <float> destinationReadView = _gd !.Map <float>(destinationReadback, MapMode.Read); float highest = 0f; highIndex = 0; for (int testNodeIndex = 0; testNodeIndex < nodeCount; testNodeIndex += 1) { int bufIndex = testNodeIndex * 4; Debug.Assert(bufIndex + 3 < destinationReadView.Count); if (Math.Abs(destinationReadView[bufIndex]) > highest) { highest = Math.Abs(destinationReadView[bufIndex]); highIndex = bufIndex; } if (Math.Abs(destinationReadView[bufIndex + 1]) > highest) { highest = Math.Abs(destinationReadView[bufIndex + 1]); highIndex = bufIndex + 1; } if (Math.Abs(destinationReadView[bufIndex + 2]) > highest) { highest = Math.Abs(destinationReadView[bufIndex + 2]); highIndex = bufIndex + 2; } } highIndex = (int)Math.Floor(highIndex / 4f); _gd.Unmap(destinationReadback); VeldridGraphBuffers.VRAMDispose(destinationReadback); return(highest); }
private void DebugPrintOutputIntBuffer(DeviceBuffer buf, string message, int printCount) { if (buf is null) { Console.WriteLine("Skipping debug output of null buffer:" + message); return; } DeviceBuffer destinationReadback = VeldridGraphBuffers.GetReadback(_gd !, buf); MappedResourceView <int> destinationReadView = _gd !.Map <int>(destinationReadback, MapMode.Read); int[] outputArray = new int[destinationReadView.Count]; for (int index = 0; index < destinationReadView.Count; index++) { if (index >= destinationReadView.Count) { break; } outputArray[index] = destinationReadView[index]; } _gd.Unmap(destinationReadback); PrintIntBufferArray(outputArray, message, printCount); VeldridGraphBuffers.VRAMDispose(destinationReadback); }
/// <summary> /// Debugging routine to find NaN values in a VRAM buffer /// </summary> /// <param name="_gd">Graphics device</param> /// <param name="buf">Buffer to search</param> /// <returns>true if NaN was found</returns> public static bool DetectNaN(GraphicsDevice _gd, DeviceBuffer buf) { DeviceBuffer destinationReadback = VeldridGraphBuffers.GetReadback(_gd, buf); MappedResourceView <float> destinationReadView = _gd.Map <float>(destinationReadback, MapMode.Read); float[] outputArray = new float[destinationReadView.Count]; for (int index = 0; index < destinationReadView.Count; index++) { if (index >= destinationReadView.Count) { break; } outputArray[index] = destinationReadView[index]; //Logging.WriteConsole($"{index}:{outputArray[index]}"); if (float.IsNaN(outputArray[index])) { Logging.WriteConsole($"{index}:{outputArray[index]}"); return(true); } } _gd.Unmap(destinationReadback); return(false); }