void CopyPixels() { // Prepare the results for CUDA // deinit CUDA interop to enable copying if (m_renderResource.IsMapped) { m_renderResource.UnMap(); } // bind pixel buffer object GL.BindBuffer(BufferTarget.PixelPackBuffer, m_sharedBufferHandle); // bind buffer from which data will be read GL.ReadBuffer(ReadBufferMode.ColorAttachment0); // read data to PBO (IntPtr.Zero means offset is 0) GL.ReadPixels(0, 0, Owner.VisualWidth, Owner.VisualHeight, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedInt8888Reversed, IntPtr.Zero); GL.ReadBuffer(ReadBufferMode.None); GL.BindBuffer(BufferTarget.PixelPackBuffer, 0); // Update the pointer for other usage in BS m_renderResource.Map(); Owner.VisualOutput.ExternalPointer = m_renderResource.GetMappedPointer <uint>().DevicePointer.Pointer; Owner.VisualOutput.FreeDevice(); Owner.VisualOutput.AllocateDevice(); // add noise over POW if (Owner.IsImageNoise) { MyKernelFactory.Instance.GetRandDevice(Owner).GenerateNormal32(Owner.AgentVisualTemp.GetDevice(Owner).DevicePointer, Owner.AgentVisualTemp.Count, Owner.ImageNoiseMean, Owner.ImageNoiseStandardDeviation); m_addRgbNoiseKernel.SetupExecution(Owner.VisualWidth * Owner.VisualHeight); m_addRgbNoiseKernel.Run(Owner.VisualOutput, Owner.VisualWidth, Owner.VisualHeight, Owner.AgentVisualTemp, 0); } }
private T InitRR <T>(T rr, MyMemoryBlock <float> targetMemBlock, MyMemoryBlock <float> targetDepthMemBlock, Action <T> initializer = null) where T : class, IRenderRequestBase { if (initializer != null) { initializer.Invoke(rr); } rr.FlipYAxis = true; targetMemBlock.ExternalPointer = 0; // first reset ExternalPointer // Setup image copying from RR through Cpu if (Owner.CopyDataThroughCPU) { ImageSettings imageSettings = new ImageSettings(RenderRequestImageCopyingMode.Cpu) { CopyDepth = Owner.CopyDepthData && targetDepthMemBlock != null, }; imageSettings.OnSceneBufferPrepared += (request, data, depthData) => { int width = rr.Resolution.Width; int stride = width * sizeof(uint); int lines = data.Length / width; for (int i = 0; i < lines; ++i) { Buffer.BlockCopy(data, i * stride, targetMemBlock.Host, i * width * sizeof(uint), stride); } if (imageSettings.CopyDepth) { for (int i = 0; i < lines; ++i) { Buffer.BlockCopy(depthData, i * stride, targetDepthMemBlock.Host, i * width * sizeof(float), stride); } } // targetMemBlock.SafeCopyToDevice(); this needs to be called on the BrainSim thread // targetDepthMemBlock.SafeCopyToDevice(); this needs to be called on the BrainSim thread }; rr.Image = imageSettings; return(rr); } // Setup image copying from RR through Pbo ImageSettings image = new ImageSettings(RenderRequestImageCopyingMode.OpenglPbo) { CopyDepth = Owner.CopyDepthData && targetDepthMemBlock != null, }; // Setup data copying to our unmanaged memblocks uint renderTextureHandle = 0; uint depthRenderTextureHandle = 0; CudaOpenGLBufferInteropResource renderResource = null; CudaOpenGLBufferInteropResource depthRenderResource = null; image.OnPreRenderingEvent += (sender, vbo, depthVbo) => { if (renderResource != null && renderResource.IsMapped) { renderResource.UnMap(); } if (image.CopyDepth) { if (depthRenderResource != null && depthRenderResource.IsMapped) { depthRenderResource.UnMap(); } } }; image.OnPostRenderingEvent += (sender, vbo, depthVbo) => { // Vbo can be allocated during drawing, create the resource after that (post-rendering) MyKernelFactory.Instance.GetContextByGPU(Owner.GPU).SetCurrent(); // Fill color memblock if (renderResource == null || vbo != renderTextureHandle) { if (renderResource != null) { renderResource.Dispose(); } renderTextureHandle = vbo; try { renderResource = new CudaOpenGLBufferInteropResource(renderTextureHandle, image.CopyDepth ? CUGraphicsRegisterFlags.None : CUGraphicsRegisterFlags.ReadOnly); // Read only by CUDA } catch (Exception e) { MyLog.ERROR.WriteLine("calling CudaOpenGLBufferInteropResource returns " + e + ". Go to World properties and in Runtime section set Copy data through CPU to True"); throw e; } } renderResource.Map(); targetMemBlock.ExternalPointer = renderResource.GetMappedPointer <uint>().DevicePointer.Pointer; targetMemBlock.FreeDevice(); targetMemBlock.AllocateDevice(); // Fill depth memblock if (image.CopyDepth) { if (depthRenderResource == null || depthVbo != depthRenderTextureHandle) { if (depthRenderResource != null) { depthRenderResource.Dispose(); } depthRenderTextureHandle = depthVbo; depthRenderResource = new CudaOpenGLBufferInteropResource( depthRenderTextureHandle, CUGraphicsRegisterFlags.ReadOnly); // Read only by CUDA } depthRenderResource.Map(); targetDepthMemBlock.ExternalPointer = depthRenderResource.GetMappedPointer <float>().DevicePointer.Pointer; targetDepthMemBlock.FreeDevice(); targetDepthMemBlock.AllocateDevice(); } }; rr.Image = image; // Initialize the target memory block // Use a dummy number that will get replaced on first Execute call to suppress MemBlock error during init targetMemBlock.ExternalPointer = 1; if (targetDepthMemBlock != null) { targetDepthMemBlock.ExternalPointer = 1; } return(rr); }