public override void Process() { Logger.Log(LogType.Log, $"Running CL Kernel: {Kernel.Name}", MIN_INSTRUCTION_SEVERITY); ArgumentResult[] results = new ArgumentResult[Arguments.Count]; Logger.Log(LogType.Log, $"[{Kernel.Name}]Computing Kernel Arguments", MIN_INSTRUCTION_SEVERITY); for (int i = 0; i < Arguments.Count; i++) { results[i] = Compute(Arguments[i]); } for (int i = 0; i < results.Length; i++) { Logger.Log(LogType.Log, $"[{Kernel.Name}]Setting Kernel Argument {Kernel.Parameter.First(x => x.Value.Id == i)}", MIN_INSTRUCTION_SEVERITY + 1); int kernelArgIndex = i + FL_HEADER_ARG_COUNT; ArgumentResult arg = results[i]; switch (arg.Type) { case FLInstructionArgumentType.Number: Kernel.SetArg(kernelArgIndex, arg.Value); //The Value is a Decimal break; case FLInstructionArgumentType.Buffer: FLBuffer bi = (FLBuffer)arg.Value; Logger.Log(LogType.Log, $"[{Kernel.Name}]Argument Buffer{bi.DefinedBufferName}", MIN_INSTRUCTION_SEVERITY + 2); Kernel.SetBuffer(kernelArgIndex, bi.Buffer); break; case FLInstructionArgumentType.Function: FLBuffer funcBuffer = (FLBuffer)arg.Value; Logger.Log(LogType.Log, $"[{Kernel.Name}]Argument Buffer{funcBuffer.DefinedBufferName}", MIN_INSTRUCTION_SEVERITY + 2); Kernel.SetBuffer(kernelArgIndex, funcBuffer.Buffer); break; default: throw new InvalidOperationException("Can not parse: " + arg.Value); } } CLAPI.Run(Root.Instance, Kernel, Root.ActiveBuffer.Buffer, Root.Dimensions, GenMaxSize, Root.ActiveChannelBuffer, 4); }
protected override void Arrange(byte[] newOrder) { MemoryBuffer newOrderBuffer = CLAPI.CreateBuffer(Root.Instance, newOrder, MemoryFlag.ReadOnly, "gpuarrange_neworder"); //Copy Active Buffer MemoryBuffer source = CLAPI.Copy <byte>(Root.Instance, Root.ActiveBuffer.Buffer); ArrangeKernel.SetBuffer(0, Root.ActiveBuffer.Buffer); ArrangeKernel.SetBuffer(1, source); ArrangeKernel.SetArg(2, Root.ActiveChannels.Length); ArrangeKernel.SetBuffer(3, newOrderBuffer); CLAPI.Run( Root.Instance, ArrangeKernel, (int)Root.ActiveBuffer.Size / Root.ActiveChannels .Length ); //Only iterating through the length as if it only has one channel. The cl kernel implementation will deal with that newOrderBuffer.Dispose(); source.Dispose(); }
private FLLineAnalysisResult AnalyzeLine(FLInstructionData data) { if (data.InstructionType != FLInstructionType.FlFunction && data.InstructionType != FLInstructionType.ClKernel) { return(FLLineAnalysisResult.ParseError); } if (leaveStack) //This keeps the stack when returning from a "function" { leaveStack = false; } else { currentArgStack = new Stack <object>(); } FLLineAnalysisResult ret = FLLineAnalysisResult.IncreasePc; for (; currentWord < data.Arguments.Count; currentWord++) //loop through the words. start value can be != 0 when returning from a function specified as an argument to a kernel { if (data.Arguments[currentWord].argType == FLArgumentType.Function) { bool keepBuffer = data.InstructionType == FLInstructionType.FlFunction && ((FLInterpreterFunctionInfo)data.Instruction).LeaveStack; JumpTo((int)data.Arguments[currentWord].value, keepBuffer); ret = FLLineAnalysisResult.Jump; //We Jumped to another point in the code. currentArgStack .Push(null); //Push null to signal the interpreter that he returned before assigning the right value. break; } if (data.Arguments[currentWord].argType != FLArgumentType.Unknown) { currentArgStack.Push(data.Arguments[currentWord].value); } } if (currentWord == data.Arguments.Count && ret != FLLineAnalysisResult.Jump) { if (data.InstructionType == FLInstructionType.FlFunction) { ((FLInterpreterFunctionInfo)data.Instruction).Run(); return(FLLineAnalysisResult.IncreasePc); } CLKernel k = (CLKernel)data.Instruction; if (k == null || data.Arguments.Count != k.Parameter.Count - FL_HEADER_ARG_COUNT) { throw new FLInvalidFunctionUseException(this.data.Source[currentIndex], "Not the right amount of arguments."); } //Execute filter for (int i = k.Parameter.Count - 1; i >= FL_HEADER_ARG_COUNT; i--) { object obj = currentArgStack.Pop(); //Get the arguments and set them to the kernel if (obj is CLBufferInfo buf) //Unpack the Buffer from the CLBuffer Object. { obj = buf.Buffer; } k.SetArg(i, obj); } Logger.Log(DebugChannel.Log | DebugChannel.OpenFL, Verbosity.Level8, "Running kernel: " + k.Name); CLAPI.Run(instance, k, currentBuffer.Buffer, new int3(width, height, depth), KernelParameter.GetDataMaxSize(kernelDb.GenDataType), activeChannelBuffer, channelCount); //Running the kernel } return(ret); }
private LineAnalysisResult AnalyzeLine(FLInstructionData data) { if (data.InstructionType != FLInstructionType.FLFunction && data.InstructionType != FLInstructionType.CLKernel) { Logger.Crash(new FLParseError(Data.Source[_currentIndex]), true); return(LineAnalysisResult.ParseError); } if (_leaveStack) //This keeps the stack when returning from a "function" { _leaveStack = false; } else { _currentArgStack = new Stack <object>(); } LineAnalysisResult ret = LineAnalysisResult.IncreasePC; for (; _currentWord < data.Arguments.Count; _currentWord++) //loop through the words. start value can be != 0 when returning from a function specified as an argument to a kernel { if (data.Arguments[_currentWord].argType == FLArgumentType.Function) { bool KeepBuffer = data.InstructionType == FLInstructionType.FLFunction && ((FLFunctionInfo)data.Instruction).LeaveStack; JumpTo((int)data.Arguments[_currentWord].value, KeepBuffer); ret = LineAnalysisResult.Jump; //We Jumped to another point in the code. _currentArgStack .Push(null); //Push null to signal the interpreter that he returned before assigning the right value. break; } if (data.Arguments[_currentWord].argType != FLArgumentType.Unknown) { _currentArgStack.Push(data.Arguments[_currentWord].value); } } if (_currentWord == data.Arguments.Count && ret != LineAnalysisResult.Jump) { if (data.InstructionType == FLInstructionType.FLFunction) { ((FLFunctionInfo)data.Instruction).Run(); return(LineAnalysisResult.IncreasePC); } CLKernel K = (CLKernel)data.Instruction; if (K == null || data.Arguments.Count != K.Parameter.Count - FLHeaderArgCount) { Logger.Crash(new FLInvalidFunctionUseException(Data.Source[_currentIndex], "Not the right amount of arguments."), true); return(LineAnalysisResult.ParseError); } //Execute filter for (int i = K.Parameter.Count - 1; i >= FLHeaderArgCount; i--) { object obj = _currentArgStack.Pop(); //Get the arguments and set them to the kernel if (obj is CLBufferInfo buf) //Unpack the Buffer from the CLBuffer Object. { obj = buf.Buffer; } K.SetArg(i, obj); } Logger.Log("Running kernel: " + K.Name, DebugChannel.Log | DebugChannel.OpenFL, 8); CLAPI.Run(K, _currentBuffer.Buffer, new int3(_width, _height, _depth), KernelParameter.GetDataMaxSize(_kernelDb.GenDataType), _activeChannelBuffer, _channelCount); //Running the kernel } return(ret); }
protected override void InitializeScene() { Add(DebugConsoleComponent.CreateConsole()); Matrix4 proj = Matrix4.CreatePerspectiveFieldOfView( MathHelper.DegreesToRadians(75f), //Field of View Vertical 16f / 9f, //Aspect Ratio 0.1f, //Near Plane 1000f); //Far Plane BasicCamera bc = new BasicCamera(proj, Vector3.Zero); Add(bc); //Adding the BasicCamera(That is a gameobject under the hood) to the scene to receive events SetCamera(bc); //Sets the Camera as the "active" camera that the scene will be rendered from. //Image size in bytes(Width * Height * ChannelCount) int imageSize = 512 * 512 * 4; //Creating a Kernel Database that will load all the Kernels contained in the asset directory KernelDatabase db = new KernelDatabase(CLAPI.MainThread, "assets/test_kernel/", DataVectorTypes.Uchar1); //We try to get the kernel_red from the file assets/test_kernel/red.cl db.TryGetClKernel("kernel_red", out CLKernel redKernel); //Creating a MemoryBuffer with size of the image. //We are using the CLAPI instance of the main thread and specify that we`d like to read/write from the buffer MemoryBuffer imageBuffer = CLAPI.CreateEmpty <byte>(CLAPI.MainThread, imageSize, MemoryFlag.ReadWrite, "CLMemoryBufferForBox"); //With plain OpenCL you would need to Set the Arguments/Buffers by their argument index/types/size/yada yads, //thanks to the CL abstraction for the engine, we can just specify the argument name how we do in OpenGL Shaders(But Faster). redKernel.SetBuffer("imageData", imageBuffer); //Set Arg has the capabilities to automatically cast the value that is passed to the right type, //however this is not really fast and can be avoided by specifying the correct type directly. redKernel.SetArg("strength", 0.5f); //We directly pass a float, no casting required //When We pass something as byte(uchar in cl), we need to cast it. //If we dont the Engine OpenCL Wrapper will automatically convert the integer into a byte, but it will apply rescaling // This takes over automatic type conversion from float(opengl) to byte(System.Bitmap/opencl) // Calculation when not passed: (4 / Int32.MaxSize) * byte.MaxValue. redKernel.SetArg("channelCount", (byte)4); //This Line runs the kernel. CLAPI.Run(CLAPI.MainThread, redKernel, imageSize); //After the kernel ran, we can read the buffer we have passed to the kernel and Convert it into a OpenGL Texture. Texture tex = TextureLoader.BytesToTexture(CLAPI.ReadBuffer <byte>(CLAPI.MainThread, imageBuffer, imageSize), 512, 512, "BoxTexture"); GameObject box = new GameObject(-Vector3.UnitZ * 4, "Box"); //Creating a new Empty GameObject LitMeshRendererComponent lmr = new LitMeshRendererComponent( //Creating a Renderer Component DefaultFilepaths.DefaultLitShader, //The OpenGL Shader used(Unlit and Lit shaders are provided) Prefabs.Cube, //The Mesh that is going to be used by the MeshRenderer tex, //Diffuse Texture to put on the mesh 1); //Render Mask (UI = 1 << 30) box.AddComponent(lmr); //Attaching the Renderer to the GameObject box.AddComponent(new RotateSelfComponent()); //Adding a component that rotates the Object on the Y-Axis Add(box); //Adding the Object to the Scene. }