// initialize renderer: takes in command line parameters passed by template code public void Init(int rt, bool gpu, int platformIdx) { // pass command line parameters runningTime = rt; useGPU = gpu; gpuPlatform = platformIdx; // initialize accumulator accumulator = new Vector3[screen.width * screen.height]; // setup scene scene = new Scene(); // setup camera camera = new Camera(screen.width, screen.height); gpuCamera = new GPUCamera(camera.pos, camera.p1, camera.p2, camera.p3, camera.up, camera.right, screen.width, screen.height, camera.lensSize); // initialize max threads parallelOptions = new ParallelOptions(); parallelOptions.MaxDegreeOfParallelism = Environment.ProcessorCount * 2; // GPU variables // pick first platform var platform = ComputePlatform.Platforms[gpuPlatform]; // create context with all gpu devices if (GLInterop) { ComputeContextProperty p1 = new ComputeContextProperty(ComputeContextPropertyName.Platform, platform.Handle.Value); ComputeContextProperty p2 = new ComputeContextProperty(ComputeContextPropertyName.CL_GL_CONTEXT_KHR, (GraphicsContext.CurrentContext as IGraphicsContextInternal).Context.Handle); ComputeContextProperty p3 = new ComputeContextProperty(ComputeContextPropertyName.CL_WGL_HDC_KHR, wglGetCurrentDC()); ComputeContextPropertyList cpl = new ComputeContextPropertyList(new ComputeContextProperty[] { p1, p2, p3 }); context = new ComputeContext(ComputeDeviceTypes.Gpu, cpl, null, IntPtr.Zero); } else { context = new ComputeContext(ComputeDeviceTypes.Gpu, new ComputeContextPropertyList(platform), null, IntPtr.Zero); } var streamReader = new StreamReader("../../program.cl"); string clSource = streamReader.ReadToEnd(); streamReader.Close(); // create program with opencl source program = new ComputeProgram(context, clSource); // compile opencl source try { program.Build(null, null, null, IntPtr.Zero); } catch { Console.Write("error in kernel code:\n"); Console.Write(program.GetBuildLog(context.Devices[0]) + "\n"); } // load chosen kernel from program kernel = program.CreateKernel("device_function"); // create some data data = new int[screen.width * screen.height]; // allocate a memory buffer with the message (the int array) var flags = ComputeMemoryFlags.WriteOnly | ComputeMemoryFlags.UseHostPointer; buffer = new ComputeBuffer<int>(context, flags, data); kernel.SetMemoryArgument(0, buffer); ComputeBuffer<float> skyboxBuffer = new ComputeBuffer<float>(context, flags, Scene.skybox); ComputeBuffer<Sphere> sphereBuffer = new ComputeBuffer<Sphere>(context, flags, Scene.sphere); ComputeBuffer<Sphere> planeBuffer = new ComputeBuffer<Sphere>(context, flags, Scene.planes); kernel.SetMemoryArgument(1, skyboxBuffer); kernel.SetValueArgument(2, gpuCamera); kernel.SetMemoryArgument(4, sphereBuffer); kernel.SetMemoryArgument(5, planeBuffer); kernel.SetValueArgument(6, Scene.light); // create a command queue with first gpu found queue = new ComputeCommandQueue(context, context.Devices[0], 0); ClearAccumulator(); // create a texture to draw to from OpenCL if (GLInterop) { texID = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, texID); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32f, 512, 512, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.Float, texData); flags = ComputeMemoryFlags.WriteOnly; texBuffer = ComputeImage2D.CreateFromGLTexture2D(context, flags, (int)TextureTarget.Texture2D, 0, texID); } // initialize dataArray int counter = 0; for (int y = 0; y < screen.height; y += 12) { for (int x = 0; x < screen.width; x += 8) { //amount.Add(new DataBundle(x, y, 12, 8)); dataArray[counter] = new DataBundle(x, y, 8, 12); counter++; } } }
// tick: renders one frame public void Tick() { //float t = 21.5f; // initialize timer if (firstFrame) { timer.Reset(); timer.Start(); firstFrame = false; } // handle keys, only when running time set to -1 (infinite) if (runningTime == -1) if (camera.HandleInput()) { // camera moved; restart ClearAccumulator(); } // render if (useGPU) { // add your CPU + OpenCL path here // mind the gpuPlatform parameter! This allows us to specify the platform on our // test system. // note: it is possible that the automated test tool provides you with a different // platform number than required by your hardware. In that case, you can hardcode // the platform during testing (ignoring gpuPlatform); do not forget to put back // gpuPlatform before submitting! GL.Finish(); // clear the screen screen.Clear(0); // do opencl stuff if (GLInterop) { kernel.SetMemoryArgument(0, texBuffer); } else { kernel.SetMemoryArgument(0, buffer); } // execute kernel //long[] workSize = { screen.width, screen.height }; long[] localSize = { 8, 12 }; long [] workSize = { screen.width , screen.height }; if (GLInterop) { List<ComputeMemory> c = new List<ComputeMemory>() { texBuffer }; queue.AcquireGLObjects(c, null); queue.Execute(kernel, null, workSize, localSize, null); queue.Finish(); queue.ReleaseGLObjects(c, null); } else { camera.Update(); gpuCamera = new GPUCamera(camera.pos, camera.p1, camera.p2, camera.p3, camera.up, camera.right, screen.width, screen.height, camera.lensSize); float scale = 1.0f / (float)++spp; kernel.SetValueArgument(2, gpuCamera); kernel.SetValueArgument(3, scale); queue.Execute(kernel, null, workSize, localSize, null); queue.Finish(); // fetch results if (!GLInterop) { queue.ReadFromBuffer(buffer, ref data, true, null); // visualize result for (int y = 0; y < screen.height; y++) for (int x = 0; x < screen.width; x++) { int temp = x + y * screen.width; screen.pixels[temp] = data[temp]; } } } } else { // this is your CPU only path float scale = 1.0f / (float)++spp; Parallel.For(0, dataArray.Length, parallelOptions, (id) => { for (int j = dataArray[id].y1; j < dataArray[id].y2 && j < screen.height; j++) { for (int i = dataArray[id].x1; i < dataArray[id].x2 && i < screen.width; i++) { // generate primary ray Ray ray = camera.Generate(RTTools.GetRNG(), i, j); // trace path int pixelIdx = i + j * screen.width; accumulator[pixelIdx] += Sample(ray, 0); // plot final color screen.pixels[pixelIdx] = RTTools.Vector3ToIntegerRGB(scale * accumulator[pixelIdx]); } } }); } // stop and report when max render time elapsed int elapsedSeconds = (int)(timer.ElapsedMilliseconds / 1000); if (runningTime != -1) if (elapsedSeconds >= runningTime) { OpenTKApp.Report((int)timer.ElapsedMilliseconds, spp, screen); } }