public CustomerEditOrderPresenter(ICustomerEditOrderView view, IContract contract) { this.contract = contract; this.customerEditOrderView = view; this.customerEditOrderView.ShowOrderInfo(); CommandList = new CommandList(); }
public static bool IsAsync(ConsoleCommand command, CommandList commands) { // Validate the command name: var found = false; Dictionary<string, ConsoleExecutingMethod> methodDictionary = null; foreach (var key in commands.Keys.Where(key => key.Namespace == command.LibraryClassName)) { found = true; methodDictionary = commands[key]; break; } if (!found) { return false; } if (!methodDictionary.ContainsKey(command.Name)) { var newCommand = char.ToUpperInvariant(command.Name[0]) + command.Name.Substring(1); if (!methodDictionary.ContainsKey(newCommand)) { return false; } command.Name = char.ToUpperInvariant(command.Name[0]) + command.Name.Substring(1); } return methodDictionary[command.Name].Async; }
private static CommandList GetCommands(IEnumerable<Type> commandClasses, Assembly assembly) { var commands = new CommandList(); foreach (var commandClass in commandClasses) { var instance = (IConsoleCommand)Activator.CreateInstance(commandClass); // Load the method info from each class into a dictionary: var methods = commandClass.GetMethods(BindingFlags.Public | BindingFlags.Instance); var methodDictionary = new Dictionary<string, ConsoleExecutingMethod>(); foreach (var method in methods) { var commandName = method.Name; if (commandName.Contains("get_Info")) continue; if (method.ReturnParameter != null && method.DeclaringType != null && method.ReturnParameter.ParameterType.FullName.Contains("ConsoleShared.ConsoleExecuteResult")) { methodDictionary.Add(commandName, new ConsoleExecutingMethod(method.DeclaringType.Namespace, assembly, method.GetParameters(), IsAsyncMethod(method))); } } // Add the dictionary of methods for the current class into a dictionary of command classes: commands.Add(new ConsoleExecutingAssembly(commandClass.Name, instance), methodDictionary); } return commands; }
public static CommandList GetCommands(Assembly assembly) { // Any static classes containing commands for use from the // console are located in the Commands namespace. Load // references to each type in that namespace via reflection: var commands = new CommandList(); // Use reflection to load all of the classes in the Commands namespace: var current = Assembly.GetExecutingAssembly(); var q = from t in current.GetTypes() where t.IsClass && typeof(IConsoleCommand).IsAssignableFrom(t) select t; var defaultCommands = GetCommands(q, current); foreach (var command in defaultCommands.Where(command => !command.Key.Namespace.Contains("get_Info"))) { commands.Add(command.Key, command.Value); } var user = from t in assembly.GetTypes() where t.IsClass && typeof(IConsoleCommand).IsAssignableFrom(t) select t; var userCommands = GetCommands(user, assembly); foreach (var command in userCommands) { commands.Add(command.Key, command.Value); } return commands; }
public void SendCommands(CommandList commands) { commands.Printer = this; foreach (Command Cmd in commands) { this.Send(Cmd.ToString()); } }
private void FormMain_Load(object sender, EventArgs e) { Console.SetOut(new TextBoxStreamWriter(Output)); try { _commandLibraries = ConsoleGetCommands.GetCommands(_commandAssembly); logControlCommand.Display("Usage is <namespace>.Command; use <namespace>.Help for command list" + Environment.NewLine); logControlCommand.Display("TAB will scroll through all commands in all namespaces" + Environment.NewLine); logControlCommand.Display("Optional parameters for commands are contained in []" + Environment.NewLine + Environment.NewLine); foreach (var command in _commandLibraries) { logControlCommand.Display(command.Key.Instance.Info.Message + Environment.NewLine); } var list = (from command in _commandLibraries from child in command.Value select command.Key.Namespace + "." + child.Key.Trim()).ToList(); shellControl1.SetCommands(list); shellControl1.CommandEntered += ShellControl1OnCommandEntered; } catch (Exception error) { logControlCommand.Display(error.ToString()); } }
/// <summary> /// Upload a character's bitmap into the current cache. /// </summary> /// <param name="character">The character specifications corresponding to the bitmap</param> public void UploadCharacterBitmap(CommandList commandList, CharacterSpecification character) { if(character.Bitmap == null) throw new ArgumentNullException("character"); if(character.IsBitmapUploaded) throw new InvalidOperationException("The character '"+character.Character+"' upload has been requested while its current glyph is valid."); var targetSize = new Int2(character.Bitmap.Width, character.Bitmap.Rows); if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect)) { // not enough space to place the new character -> remove less used characters and try again RemoveLessUsedCharacters(); if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect)) { // memory is too fragmented in order to place the new character -> clear all the characters and restart. ClearCache(); if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect)) throw new InvalidOperationException("The rendered character is too big for the cache texture"); } } // updload the bitmap on the texture (if the size in the bitmap is not null) if (character.Bitmap.Rows != 0 && character.Bitmap.Width != 0) { var dataBox = new DataBox(character.Bitmap.Buffer, character.Bitmap.Pitch, character.Bitmap.Pitch * character.Bitmap.Rows); var region = new ResourceRegion(character.Glyph.Subrect.Left, character.Glyph.Subrect.Top, 0, character.Glyph.Subrect.Right, character.Glyph.Subrect.Bottom, 1); commandList.UpdateSubresource(cacheTextures[0], 0, dataBox, region); } // update the glyph data character.IsBitmapUploaded = true; character.Glyph.BitmapIndex = 0; }
public CommandListParser(IContract contract, CommandList commandList, ClientOrder order, User user) { this.contract = contract; this.commandList = commandList; this.order = order; this.user = user; }
public Program() { Name = ""; CommandList = new CommandList(); Functions = new List<UserDefinedFunction>(); UserDefinedTypes = new TypeDescriptors(); //EntryPoints = new Dictionary<UserDefinedFunction, int>(); }
protected virtual void InitMenu() { if (Menu == null) { Menu = new CommandList(); Menu.Add(new CutCommand(this)); Menu.Add(new CopyCommand(this)); Menu.Add(new PasteCommand(this)); } }
/// <summary> /// 명령어의 최소 요구 매개변수 개수를 가져옵니다. /// </summary> /// <param name="command">해당 명령어를 가리킵니다.</param> /// <returns>이 명령어의 최소 요구 매개변수 개수입니다.</returns> public int MinArgumentNumber(CommandList command) { IEnumerable<XElement> foundCommand = from consoleCommand in this.targetXmlFile.Root.Elements("Command") where consoleCommand.Attribute("type").Value == command.ToString() select consoleCommand; IEnumerable<string> interpretTag = from foundElem in foundCommand.Elements("Arguments") select foundElem.Element("min").Value; return int.Parse(interpretTag.ToArray<string>()[0]); }
public TrinketSpawnConfiguration GetGameConfiguration(CommandList commandList) { return new TrinketSpawnConfigurationImpl { Name = "GAME", IsDebugEnabled = true, IsCommandingEnabled = true, CommandList = commandList, IsFileSystemHookingEnabled = true, IsFileSystemOverridingEnabled = true, IsLoggingEnabled = true }; }
/// <summary> /// 주어진 매개변수를 통해 상황에 맞는 메시지를 불러옵니다. /// </summary> /// <param name="command">현재 사용하고자 하는 명령어입니다.</param> /// <param name="info">명령어의 입력 상태를 가리킵니다.</param> /// <returns>주어진 값에 대한 정보 메시지입니다.</returns> public string Message(CommandList command, CommandInfoList info) { IEnumerable<XElement> foundCommand = from consoleCommand in this.targetXmlFile.Root.Elements("Command") where consoleCommand.Attribute("type").Value == command.ToString() select consoleCommand; IEnumerable<string> interpretedTag = from resultElem in foundCommand.ToArray()[0].Element("Messages").Elements("message") where resultElem.Attribute("cause").Value == info.ToString() select resultElem.Value; return interpretedTag.ToArray<string>()[0]; }
public ICommandList Bind(IComparable commandTrigger) { if (!HasBinding(commandTrigger)) { ICommandList cmdList = new CommandList(); _commandLists.Add(commandTrigger, cmdList); return cmdList; } else { throw new Exception("commandTrigger already used"); } }
public void Render() { Delegate[] Handlers = CommandListBuildHandler.GetInvocationList(); CommandList[] List = new CommandList[Handlers.Length]; Parallel.For(0, Handlers.Length,Index => { ((CommandListDelegate)Handlers[Index])(CommandPool[Index].CommandList,CommandPool[Index].Allocator); List[Index] = CommandPool[Index].CommandList; }); GraphicCommandQueue.ExecuteCommandLists(CommandPool.Count,List); SwapChain.Present(1, 0); WaitForPreviousFrame(); }
/// <summary> /// 현재 명령어의 매개 변수 개수가 올바른지 검사합니다. false는 너무 많은 매개변수, null은 너무 적은 매개변수를 가리킵니다. true는 정상 입력입니다. /// </summary> /// <param name="command">현재 명령어를 가리킵니다.</param> /// <param name="userInput">들어온 문자열 Input을 가리킵니다.</param> /// <returns>성공 여부입니다.</returns> public bool? CheckArgumentNumber(CommandList command, string userInput) { string[] splitInput = userInput.Split(' '); if (splitInput.Length > this.xmlReader.MaxArgumentNumber(command)) { return false; } else if (splitInput.Length < this.xmlReader.MinArgumentNumber(command)) { return null; } else { return true; } }
internal void Finish() { if(!m_finished && m_deferred) { m_finished = true; m_commandList = Context.FinishCommandList(false); } }
public unsafe void UpdateCameraBuffers(CommandList cl) { cl.UpdateBuffer(ProjectionMatrixBuffer, 0, Camera.ProjectionMatrix); cl.UpdateBuffer(ViewMatrixBuffer, 0, Camera.ViewMatrix); cl.UpdateBuffer(CameraInfoBuffer, 0, Camera.GetCameraInfo()); }
public Bitmap DrawToBitmap(CommandList commands) { InitPen(); Bitmap curBitmap = new Bitmap(RenderSize.Width, RenderSize.Height); Graphics g1 = Graphics.FromImage(curBitmap); g1.InterpolationMode = InterpolationMode.NearestNeighbor; g1.SmoothingMode = SmoothingMode.None; g1.PixelOffsetMode = PixelOffsetMode.None; g1.CompositingQuality = CompositingQuality.HighSpeed; g1.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel; var ee = new PaintEventArgs(g1, new Rectangle()); var pts = new PointF[] { ToClientF(new Point3D(0, 0, 0)), ToClientF(new Point3D(0, SizeY, 0)), ToClientF(new Point3D(SizeX, SizeY, 0)), ToClientF(new Point3D(SizeX, 0, 0)) }; g1.FillPolygon(new SolidBrush(MachineColor), pts); for (int i = 1; ; i++) { var x = i * 10.0; if (x > SizeX) break; g1.DrawLine(((i % 10) == 0) ? _helpLinePen10 : _helpLinePen, ToClientF(new Point3D(i * 10.0, 0, 0)), ToClientF(new Point3D(i * 10.0, SizeY, 0))); } for (int i = 1; ; i++) { var y = i * 10.0; if (y > SizeY) break; g1.DrawLine(((i % 10) == 0) ? _helpLinePen10 : _helpLinePen, ToClientF(new Point3D(0, i * 10.0, 0)), ToClientF(new Point3D(SizeX, i * 10.0, 0))); } commands?.Paint(this, ee); g1.Dispose(); return curBitmap; }
private void ProcessSetViewport(CommandList cl, RenderCommandQueueItem command) { _viewportManager.SetActiveViewport(command.SpareId0); }
/// <summary> /// Example of how to render the 6-sides within threads. Note: this is not compatible with running threads for the mesh renderers in /// the renderScene action. /// </summary> /// <param name="renderScene">The method that will render the scene</param> public void UpdateThreaded(Action<DeviceContext, Matrix, Matrix, RenderTargetView, DepthStencilView, DynamicCubeMap> renderScene) { // Don't render the reflector itself if (Reflector != null) { Reflector.Show = false; } var contexts = contextList ?? new DeviceContext[] { this.RenderContext }; CommandList[] commands = new CommandList[contexts.Length]; int batchSize = 6 / contexts.Length; Task[] tasks = new Task[contexts.Length]; for (var i = 0; i < contexts.Length; i++) { var contextIndex = i; tasks[i] = Task.Run(() => { var context = contexts[contextIndex]; int startIndex = batchSize * contextIndex; int endIndex = Math.Min(startIndex + batchSize, 5); if (contextIndex == contexts.Length - 1) endIndex = 5; // Use "draw" to render the scene for each face of the cubemap for (var j = startIndex; j <= endIndex; j++) { UpdateCubeFace(context, j, renderScene); } if (context.TypeInfo == DeviceContextType.Deferred) commands[contextIndex] = ToDispose(context.FinishCommandList(false)); }); } Task.WaitAll(tasks); // Execute command lists (if any) for (var i = 0; i < contexts.Length; i++) { if (contexts[i].TypeInfo == DeviceContextType.Deferred && commands[i] != null) { DeviceManager.Direct3DDevice.ImmediateContext.ExecuteCommandList(commands[i], false); commands[i].Dispose(); commands[i] = null; } } // Re-enable the Reflector if (Reflector != null) { Reflector.Show = true; } }
// TODO: Cleanup public Texture CreateDeviceTexture(GraphicsDevice gd, ResourceFactory rf, TextureUsage usage) { if (gd == null) { throw new ArgumentNullException(nameof(gd)); } if (rf == null) { throw new ArgumentNullException(nameof(rf)); } using var _ = PerfTracker.FrameEvent("6.1.2.1 Rebuild MultiTextures"); if (IsMetadataDirty) { RebuildLayers(); } var palette = PaletteManager.Palette.GetCompletePalette(); using var staging = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format.ToVeldrid(), TextureUsage.Staging, Type)); staging.Name = "T_" + Name + "_Staging"; Span <uint> toBuffer = stackalloc uint[(int)(Width * Height)]; foreach (var lsi in LogicalSubImages) { //if (!rebuildAll && !lsi.IsPaletteAnimated) // TODO: Requires caching a single Texture and then modifying it // continue; for (int i = 0; i < lsi.Frames; i++) { toBuffer.Fill(lsi.IsAlphaTested ? 0 : 0xff000000); Rebuild(lsi, i, toBuffer, palette); uint destinationLayer = (uint)LayerLookup[new LayerKey(lsi.Id, i)]; unsafe { fixed(uint *toBufferPtr = toBuffer) { gd.UpdateTexture( staging, (IntPtr)toBufferPtr, Width * Height * sizeof(uint), 0, 0, 0, Width, Height, 1, 0, destinationLayer); } } } } /* TODO: Mipmap * for (uint level = 1; level < MipLevels; level++) * { * } //*/ var texture = rf.CreateTexture(new TextureDescription(Width, Height, Depth, MipLevels, ArrayLayers, Format.ToVeldrid(), usage, Type)); texture.Name = "T_" + Name; using (CommandList cl = rf.CreateCommandList()) { cl.Begin(); cl.CopyTexture(staging, texture); cl.End(); gd.SubmitCommands(cl); } IsDirty = false; return(texture); }
public new void SendToRenderStage(IRenderStageVisitor visitor, CommandList cl, RenderCommandQueueItem command) => visitor.DispatchToRenderStage(this, cl, command);
public abstract void Render(GraphicsDevice gd, CommandList cl, SceneContext sc, RenderPasses renderPass);
protected override Glyph GetGlyph(CommandList commandList, char character, in Vector2 fontSize, bool dumb, out Vector2 fixScaling)
public abstract void CreateDeviceObjects(GraphicsDevice gd, CommandList cl, SceneContext sc);
public abstract void UpdatePerFrameResources(GraphicsDevice gd, CommandList cl, SceneContext sc);
public void Render(CommandList cl) { }
private void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd, CommandList cl) { uint vertexOffsetInVertices = 0; uint indexOffsetInElements = 0; if (draw_data.CmdListsCount == 0) { return; } uint totalVBSize = (uint)(draw_data.TotalVtxCount * Unsafe.SizeOf <ImDrawVert>()); if (totalVBSize > _vertexBuffer.SizeInBytes) { gd.DisposeWhenIdle(_vertexBuffer); _vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalVBSize * 1.5f), BufferUsage.VertexBuffer | BufferUsage.Dynamic)); } uint totalIBSize = (uint)(draw_data.TotalIdxCount * sizeof(ushort)); if (totalIBSize > _indexBuffer.SizeInBytes) { gd.DisposeWhenIdle(_indexBuffer); _indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalIBSize * 1.5f), BufferUsage.IndexBuffer | BufferUsage.Dynamic)); } for (int i = 0; i < draw_data.CmdListsCount; i++) { ImDrawListPtr cmd_list = draw_data.CmdListsRange[i]; cl.UpdateBuffer( _vertexBuffer, vertexOffsetInVertices * (uint)Unsafe.SizeOf <ImDrawVert>(), cmd_list.VtxBuffer.Data, (uint)(cmd_list.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>())); cl.UpdateBuffer( _indexBuffer, indexOffsetInElements * sizeof(ushort), cmd_list.IdxBuffer.Data, (uint)(cmd_list.IdxBuffer.Size * sizeof(ushort))); vertexOffsetInVertices += (uint)cmd_list.VtxBuffer.Size; indexOffsetInElements += (uint)cmd_list.IdxBuffer.Size; } // Setup orthographic projection matrix into our constant buffer ImGuiIOPtr io = ImGui.GetIO(); Matrix4x4 mvp = Matrix4x4.CreateOrthographicOffCenter( 0f, io.DisplaySize.X, io.DisplaySize.Y, 0.0f, -1.0f, 1.0f); _gd.UpdateBuffer(_projMatrixBuffer, 0, ref mvp); cl.SetVertexBuffer(0, _vertexBuffer); cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16); cl.SetPipeline(_pipeline); cl.SetGraphicsResourceSet(0, _mainResourceSet); draw_data.ScaleClipRects(io.DisplayFramebufferScale); // Render command lists int vtx_offset = 0; int idx_offset = 0; for (int n = 0; n < draw_data.CmdListsCount; n++) { ImDrawListPtr cmd_list = draw_data.CmdListsRange[n]; for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++) { ImDrawCmdPtr pcmd = cmd_list.CmdBuffer[cmd_i]; if (pcmd.UserCallback != IntPtr.Zero) { throw new NotImplementedException(); } else { if (pcmd.TextureId != IntPtr.Zero) { if (pcmd.TextureId == _fontAtlasID) { cl.SetGraphicsResourceSet(1, _fontTextureResourceSet); } else { cl.SetGraphicsResourceSet(1, GetImageResourceSet(pcmd.TextureId)); } } cl.SetScissorRect( 0, (uint)pcmd.ClipRect.X, (uint)pcmd.ClipRect.Y, (uint)(pcmd.ClipRect.Z - pcmd.ClipRect.X), (uint)(pcmd.ClipRect.W - pcmd.ClipRect.Y)); cl.DrawIndexed(pcmd.ElemCount, 1, (uint)idx_offset, vtx_offset, 0); } idx_offset += (int)pcmd.ElemCount; } vtx_offset += cmd_list.VtxBuffer.Size; } }
private void ProcessClearViewport(CommandList cl, RenderCommandQueueItem command) { _viewportManager.ClearActiveViewport(); }
public void Run() { // Initial state var currentState = new State { // Set the number of cubes to display (horizontally and vertically) CountCubes = 64, // Number of threads to run concurrently ThreadCount = 4, // Use deferred by default Type = TestType.Deferred, // BurnCpu by default SimulateCpuUsage = true, // Default is using Map/Unmap UseMap = true, }; var nextState = currentState; // -------------------------------------------------------------------------------------- // Init Direct3D11 // -------------------------------------------------------------------------------------- // Create the Rendering form var form = new RenderForm("SharpDX - MiniCube Direct3D11"); form.ClientSize = new Size(1024, 1024); // SwapChain description var desc = new SwapChainDescription() { BufferCount = 2, ModeDescription = new ModeDescription(form.ClientSize.Width, form.ClientSize.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm), IsWindowed = true, OutputHandle = form.Handle, SampleDescription = new SampleDescription(1, 0), SwapEffect = SwapEffect.Discard, Usage = Usage.RenderTargetOutput }; // Create Device and SwapChain Device device; SwapChain swapChain; Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out device, out swapChain); var immediateContext = device.ImmediateContext; device = ToDispose(device); // PreCreate deferred contexts var deferredContexts = new DeviceContext[MaxNumberOfThreads]; for (int i = 0; i < deferredContexts.Length; i++) deferredContexts[i] = ToDispose(new DeviceContext(device)); // Allocate rendering context array var contextPerThread = new DeviceContext[MaxNumberOfThreads]; contextPerThread[0] = immediateContext; var commandLists = new CommandList[MaxNumberOfThreads]; CommandList[] frozenCommandLists = null; // Check if driver is supporting natively CommandList bool supportConcurentResources; bool supportCommandList; device.CheckThreadingSupport(out supportConcurentResources, out supportCommandList); // Ignore all windows events var factory = ToDispose(swapChain.GetParent<Factory>()); factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll); // New RenderTargetView from the backbuffer var backBuffer = ToDispose(Texture2D.FromSwapChain<Texture2D>(swapChain, 0)); var renderView = ToDispose(new RenderTargetView(device, backBuffer)); // Compile Vertex and Pixel shaders var bytecode = ShaderBytecode.Compile(Resources.MultiCube, "VS", "vs_4_0"); var vertexShader = ToDispose(new VertexShader(device, bytecode)); // Layout from VertexShader input signature var layout = ToDispose(new InputLayout(device, ToDispose(ShaderSignature.GetInputSignature(bytecode)), new[] { new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0) })); bytecode.Dispose(); bytecode = ToDispose(ShaderBytecode.Compile(Resources.MultiCube, "PS", "ps_4_0")); var pixelShader = ToDispose(new PixelShader(device, bytecode)); bytecode.Dispose(); // Instantiate Vertex buiffer from vertex data var vertices = ToDispose(Buffer.Create(device, BindFlags.VertexBuffer, new[] { new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), new Vector4(-1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom new Vector4( 1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), new Vector4(-1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), new Vector4(-1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), new Vector4( 1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), new Vector4( 1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), })); // Create Constant Buffer var staticContantBuffer = ToDispose(new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0)); var dynamicConstantBuffer = ToDispose(new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Dynamic, BindFlags.ConstantBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0)); // Create Depth Buffer & View var depthBuffer = ToDispose(new Texture2D(device, new Texture2DDescription() { Format = Format.D32_Float_S8X24_UInt, ArraySize = 1, MipLevels = 1, Width = form.ClientSize.Width, Height = form.ClientSize.Height, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None })); var depthView = ToDispose(new DepthStencilView(device, depthBuffer)); // -------------------------------------------------------------------------------------- // Prepare matrices & clocks // -------------------------------------------------------------------------------------- const float viewZ = 5.0f; // Prepare matrices var view = Matrix.LookAtLH(new Vector3(0, 0, -viewZ), new Vector3(0, 0, 0), Vector3.UnitY); var proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, form.ClientSize.Width / (float)form.ClientSize.Height, 0.1f, 100.0f); var viewProj = Matrix.Multiply(view, proj); // Use clock var clock = new Stopwatch(); clock.Start(); var fpsTimer = new Stopwatch(); fpsTimer.Start(); int fpsCounter = 0; // -------------------------------------------------------------------------------------- // Register KeyDown event handler on the form // -------------------------------------------------------------------------------------- bool switchToNextState = false; // Install keys handlers form.KeyDown += (target, arg) => { if (arg.KeyCode == Keys.Left && nextState.CountCubes > 1) nextState.CountCubes--; if (arg.KeyCode == Keys.Right && nextState.CountCubes < MaxNumberOfCubes) nextState.CountCubes++; if (arg.KeyCode == Keys.F1) nextState.Type= (TestType)((((int)nextState.Type) + 1) % 3); if (arg.KeyCode == Keys.F2) nextState.UseMap = !nextState.UseMap; if (arg.KeyCode == Keys.F3) nextState.SimulateCpuUsage = !nextState.SimulateCpuUsage; if (nextState.Type == TestType.Deferred) { if (arg.KeyCode == Keys.Down && nextState.ThreadCount > 1) nextState.ThreadCount--; if (arg.KeyCode == Keys.Up && nextState.ThreadCount < MaxNumberOfThreads) nextState.ThreadCount++; } if (arg.KeyCode == Keys.Escape) nextState.Exit = true; switchToNextState = true; }; // -------------------------------------------------------------------------------------- // Function used to setup the pipeline // -------------------------------------------------------------------------------------- Action SetupPipeline = () => { int threadCount = 1; if (currentState.Type != TestType.Immediate) { threadCount = currentState.Type == TestType.Deferred ? currentState.ThreadCount : 1; Array.Copy(deferredContexts, contextPerThread, contextPerThread.Length); } else { contextPerThread[0] = immediateContext; } for (int i = 0; i < threadCount; i++) { var renderingContext = contextPerThread[i]; // Prepare All the stages renderingContext.InputAssembler.InputLayout = layout; renderingContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; renderingContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0)); renderingContext.VertexShader.SetConstantBuffer(0, currentState.UseMap ? dynamicConstantBuffer : staticContantBuffer); renderingContext.VertexShader.Set(vertexShader); renderingContext.Rasterizer.SetViewport(0, 0, form.ClientSize.Width, form.ClientSize.Height); renderingContext.PixelShader.Set(pixelShader); renderingContext.OutputMerger.SetTargets(depthView, renderView); } }; // -------------------------------------------------------------------------------------- // Function used to render a row of cubes // -------------------------------------------------------------------------------------- Action<int, int, int> RenderRow = (int contextIndex, int fromY, int toY) => { var renderingContext = contextPerThread[contextIndex]; var time = clock.ElapsedMilliseconds / 1000.0f; if (contextIndex == 0) { contextPerThread[0].ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1.0f, 0); contextPerThread[0].ClearRenderTargetView(renderView, Color.Black); } int count = currentState.CountCubes; float divCubes = (float)count / (viewZ - 1); var rotateMatrix = Matrix.Scaling(1.0f / count) * Matrix.RotationX(time) * Matrix.RotationY(time * 2) * Matrix.RotationZ(time * .7f); for (int y = fromY; y < toY; y++) { for (int x = 0; x < count; x++) { rotateMatrix.M41 = (x + .5f - count * .5f) / divCubes; rotateMatrix.M42 = (y + .5f - count * .5f) / divCubes; // Update WorldViewProj Matrix Matrix worldViewProj; Matrix.Multiply(ref rotateMatrix, ref viewProj, out worldViewProj); worldViewProj.Transpose(); // Simulate CPU usage in order to see benefits of worlViewProj if (currentState.SimulateCpuUsage) { for (int i = 0; i < BurnCpuFactor; i++) { Matrix.Multiply(ref rotateMatrix, ref viewProj, out worldViewProj); worldViewProj.Transpose(); } } if (currentState.UseMap) { var dataBox = renderingContext.MapSubresource(dynamicConstantBuffer, 0, MapMode.WriteDiscard, MapFlags.None); Utilities.Write(dataBox.DataPointer, ref worldViewProj); renderingContext.UnmapSubresource(dynamicConstantBuffer, 0); } else { renderingContext.UpdateSubresource(ref worldViewProj, staticContantBuffer); } // Draw the cube renderingContext.Draw(36, 0); } } if (currentState.Type != TestType.Immediate) commandLists[contextIndex] = renderingContext.FinishCommandList(false); }; Action<int> RenderDeferred = (int threadCount) => { int deltaCube = currentState.CountCubes / threadCount; if (deltaCube == 0) deltaCube = 1; int nextStartingRow = 0; var tasks = new Task[threadCount]; for (int i = 0; i < threadCount; i++) { var threadIndex = i; int fromRow = nextStartingRow; int toRow = (i + 1) == threadCount ? currentState.CountCubes : fromRow + deltaCube; if (toRow > currentState.CountCubes) toRow = currentState.CountCubes; nextStartingRow = toRow; tasks[i] = new Task(() => RenderRow(threadIndex, fromRow, toRow) ); tasks[i].Start(); } Task.WaitAll(tasks); }; // -------------------------------------------------------------------------------------- // Main Loop // -------------------------------------------------------------------------------------- RenderLoop.Run(form, () => { if (currentState.Exit) form.Close(); fpsCounter++; if (fpsTimer.ElapsedMilliseconds > 1000) { var typeStr = currentState.Type.ToString(); if (currentState.Type != TestType.Immediate && !supportCommandList) typeStr += "*"; form.Text = string.Format("SharpDX - MultiCube D3D11 - (F1) {0} - (F2) {1} - (F3) {2} - Threads ↑↓{3} - Count ←{4}→ - FPS: {5:F2} ({6:F2}ms)", typeStr, currentState.UseMap ? "Map/UnMap" : "UpdateSubresource", currentState.SimulateCpuUsage ? "BurnCPU On" : "BurnCpu Off", currentState.Type == TestType.Deferred ? currentState.ThreadCount : 1, currentState.CountCubes * currentState.CountCubes, 1000.0 * fpsCounter / fpsTimer.ElapsedMilliseconds, (float)fpsTimer.ElapsedMilliseconds / fpsCounter); fpsTimer.Reset(); fpsTimer.Stop(); fpsTimer.Start(); fpsCounter = 0; } // Setup the pipeline before any rendering SetupPipeline(); // Execute on the rendering thread when ThreadCount == 1 or No deferred rendering is selected if (currentState.Type == TestType.Immediate || ( currentState.Type == TestType.Deferred && currentState.ThreadCount == 1)) { RenderRow(0, 0, currentState.CountCubes); } // In case of deferred context, use of FinishCommandList / ExecuteCommandList if (currentState.Type != TestType.Immediate) { if (currentState.Type == TestType.FrozenDeferred) { if (commandLists[0] == null) RenderDeferred(1); } else if (currentState.ThreadCount > 1) { RenderDeferred(currentState.ThreadCount); } for (int i = 0; i < currentState.ThreadCount; i++) { var commandList = commandLists[i]; // Execute the deferred command list on the immediate context immediateContext.ExecuteCommandList(commandList, false); // For classic deferred we release the command list. Not for frozen if (currentState.Type == TestType.Deferred) { // Release the command list commandList.Dispose(); commandLists[i] = null; } } } if (switchToNextState) { currentState = nextState; switchToNextState = false; } // Present! swapChain.Present(0, PresentFlags.None); }); // Dispose all resource created Dispose(); }
public abstract void Commit(CommandList commandList, Texture renderFrame);
/// <summary> /// Joins every user-defined function to the end of the command list. /// After calling this function you should NOT change the command list. /// </summary> public void JoinCommands() { if (!isJoined) { originalCommandList = CommandList; CommandList = new CommandList(); CommandList.AddRange(originalCommandList); if (CommandList.Count > 0 && !(CommandList.Last() is Return)) { CommandList.Add(new Return(false)); } //EntryPoints.Clear(); foreach (var udf in Functions) { //EntryPoints.Add(udf, CommandList.Count); udf.EntryPoint = CommandList.Count; CommandList.AddRange(udf.Commands); } isJoined = true; } }
public void Deserialize(IPofReader reader) { this.commandList = reader.ReadObject<CommandList>(0); this.initializationLatch.Signal(); }
protected override void Draw(GameTimer gt) { CommandAllocator cmdListAlloc = CurrFrameResource.CmdListAlloc; // Reuse the memory associated with command recording. // We can only reset when the associated command lists have finished execution on the GPU. cmdListAlloc.Reset(); // A command list can be reset after it has been added to the command queue via ExecuteCommandList. // Reusing the command list reuses memory. CommandList.Reset(cmdListAlloc, _psos["opaque"]); CommandList.SetViewport(Viewport); CommandList.SetScissorRectangles(ScissorRectangle); // Indicate a state transition on the resource usage. CommandList.ResourceBarrierTransition(CurrentBackBuffer, ResourceStates.Present, ResourceStates.RenderTarget); // Clear the back buffer and depth buffer. CommandList.ClearRenderTargetView(CurrentBackBufferView, new Color(_mainPassCB.FogColor)); CommandList.ClearDepthStencilView(DepthStencilView, ClearFlags.FlagsDepth | ClearFlags.FlagsStencil, 1.0f, 0); // Specify the buffers we are going to render to. CommandList.SetRenderTargets(CurrentBackBufferView, DepthStencilView); CommandList.SetDescriptorHeaps(_descriptorHeaps.Length, _descriptorHeaps); CommandList.SetGraphicsRootSignature(_rootSignature); // Bind per-pass constant buffer. We only need to do this once per-pass. Resource passCB = CurrFrameResource.PassCB.Resource; CommandList.SetGraphicsRootConstantBufferView(2, passCB.GPUVirtualAddress); DrawRenderItems(CommandList, _ritemLayers[RenderLayer.Opaque]); CommandList.PipelineState = _psos["alphaTested"]; DrawRenderItems(CommandList, _ritemLayers[RenderLayer.AlphaTested]); CommandList.PipelineState = _psos["transparent"]; DrawRenderItems(CommandList, _ritemLayers[RenderLayer.Transparent]); // Indicate a state transition on the resource usage. CommandList.ResourceBarrierTransition(CurrentBackBuffer, ResourceStates.RenderTarget, ResourceStates.Present); // Done recording commands. CommandList.Close(); // Add the command list to the queue for execution. CommandQueue.ExecuteCommandList(CommandList); // Present the buffer to the screen. Presenting will automatically swap the back and front buffers. SwapChain.Present(0, PresentFlags.None); // Advance the fence value to mark commands up to this fence point. CurrFrameResource.Fence = ++CurrentFence; // Add an instruction to the command queue to set a new fence point. // Because we are on the GPU timeline, the new fence point won't be // set until the GPU finishes processing all the commands prior to this Signal(). CommandQueue.Signal(Fence, CurrentFence); }
public void Render(GraphicsDevice gd, CommandList cl, GraphicsSystem sc, RenderPasses renderPass) { Debug.Assert(renderPass == Glitch.Graphics.RenderPasses.Overlay); _imguiRenderer.Render(gd, cl); }
public void Render(RenderContext context, IPipeline pipeline, IViewport viewport, CommandList cl) { var builders = _sceneBuilder.BufferBuilders.ToList(); foreach (var buffer in builders) { for (var i = 0; i < buffer.NumBuffers; i++) { var groups = buffer.IndirectBufferGroups[i].Where(x => x.Pipeline == pipeline.Type && !x.HasTransparency).Where(x => x.Camera == CameraType.Both || x.Camera == viewport.Camera.Type).ToList(); if (!groups.Any()) { continue; } cl.SetVertexBuffer(0, buffer.VertexBuffers[i]); cl.SetIndexBuffer(buffer.IndexBuffers[i], IndexFormat.UInt32); foreach (var bg in groups) { pipeline.Bind(context, cl, bg.Binding); buffer.IndirectBuffers[i].DrawIndexed(cl, bg.Offset * IndSize, bg.Count, 20); } } } }
[STAThread] // Needed for ASIOOutput.StartDriver method static void Main(string[] args) { // Create window, GraphicsDevice, and all resources necessary for the demo. VeldridStartup.CreateWindowAndGraphicsDevice( new WindowCreateInfo(50, 50, 3600, 2000, WindowState.Normal, "Vector Engine Editor"), new GraphicsDeviceOptions(true, null, true), out _window, out _gd); _gd.MainSwapchain.SyncToVerticalBlank = false; _window.Resized += () => { _gd.MainSwapchain.Resize((uint)_window.Width, (uint)_window.Height); _controller.WindowResized(_window.Width, _window.Height); }; _cl = _gd.ResourceFactory.CreateCommandList(); _controller = new ImGuiController(_gd, _gd.MainSwapchain.Framebuffer.OutputDescription, _window.Width, _window.Height); string assetsPath = HostHelper.AssetsPath; FileLoader.Init(assetsPath); FileLoader.LoadAllComponentGroups(); if (_showEditor) { HostHelper.StopGame(true); } else { HostHelper.PlayGame(true); } // Main application loop while (_window.Exists) { GameLoop.Tick(); InputSnapshot snapshot = _window.PumpEvents(); if (!_window.Exists) { break; } foreach (var keypress in snapshot.KeyEvents) { if (keypress.Key == Key.E && keypress.Down && keypress.Modifiers == ModifierKeys.Control) { _showEditor = !_showEditor; } if (keypress.Key == Key.S && keypress.Down && keypress.Modifiers == ModifierKeys.Control) { HostHelper.SaveScene(); } if (keypress.Key == Key.D && keypress.Down && keypress.Modifiers == ModifierKeys.Control) { HostHelper.Duplicate(); } } if (_showEditor) { if (EditorCamera == null) { foreach (var component in EntityAdmin.Instance.Components) { if (component.Entity.Name == EmptyScene.EDITOR_CAM_ENTITY_NAME) { EditorCamera = component.Entity; break; } } } if (midi == null) { midi = new MIDI(); midi.SetupWatchersAndPorts(); while (!midi.SetupComplete) { Thread.Sleep(1); } } IMidiMessage midiMessage; while (midi.MidiMessageQueue.TryDequeue(out midiMessage)) { MidiState.UpdateState(midiMessage); } // TODO: figure out why LastFrameTime makes ImGui run stupid fast... (for things like key repeats) _controller.Update(GameTime.LastFrameTime / 10f, snapshot); // Feed the input events to our ImGui controller, which passes them through to ImGui. EditorUI.SubmitUI(EntityAdmin.Instance); _cl.Begin(); _cl.SetFramebuffer(_gd.MainSwapchain.Framebuffer); _cl.ClearColorTarget(0, new RgbaFloat(ClearColor.X, ClearColor.Y, ClearColor.Z, 1f)); _controller.Render(_gd, _cl); _cl.End(); _gd.SubmitCommands(_cl); _gd.SwapBuffers(_gd.MainSwapchain); } } if (!HostHelper.PlayingGame) { HostHelper.SaveScene(); } // Clean up Veldrid resources _gd.WaitForIdle(); _controller.Dispose(); _cl.Dispose(); _gd.Dispose(); }
public void UpdatePerFrameResources(GraphicsDevice gd, CommandList cl, GraphicsSystem sc) { }
void IInitializable.Initialize() { m_listbox = new CommandList(); m_listbox.DrawMode = DrawMode.OwnerDrawFixed; m_listbox.BorderStyle = BorderStyle.None; m_listbox.SelectedIndexChanged += (sender, e) => { try { m_undoingOrRedoing = true; int indexLastDone = m_commandHistory.Current - 1; int cmdIndex = m_listbox.SelectedIndex + m_startIndex; if (cmdIndex < indexLastDone) { while (cmdIndex < indexLastDone) { m_historyContext.Undo(); indexLastDone = m_commandHistory.Current - 1; } } else { while (cmdIndex >= m_commandHistory.Current) m_historyContext.Redo(); } } finally { m_undoingOrRedoing = false; } }; m_listbox.DrawItem2 += (sender, e) => { if (e.Index < 0) return; int cmdIndex = e.Index + m_startIndex; Command cmd = (Command)m_listbox.Items[e.Index]; if(cmdIndex >= m_commandHistory.Current) { m_textBrush.Color = m_redoForeColor; m_fillBrush.Color = m_redoBackColor; } else { m_textBrush.Color = m_undoForeColor; m_fillBrush.Color = m_undoBackColor; } if (e.State == DrawItemState.Selected) { e.DrawBackground(); e.DrawFocusRectangle(); } else { e.Graphics.FillRectangle(m_fillBrush, e.Bounds); } e.Graphics.DrawString(cmd.Description, e.Font, m_textBrush, e.Bounds, StringFormat.GenericDefault); }; ControlInfo cinfo = new ControlInfo("History", "Undo/Redo stack", StandardControlGroup.Right); m_controlHostService.RegisterControl(m_listbox, cinfo, null); m_documentRegistry.ActiveDocumentChanged += m_documentRegistry_ActiveDocumentChanged; m_listbox.BackColorChanged += (sender, e) => ComputeColors(); m_listbox.ForeColorChanged += (sender, e) => ComputeColors(); if (m_settingsService != null) { var descriptor = new BoundPropertyDescriptor( this, () => MaxCommandCount, "Max Visual Command History Count".Localize(), null, "Maximum number of commands in the visual command history. Minimum value is 10".Localize()); m_settingsService.RegisterSettings(this, descriptor); m_settingsService.RegisterUserSettings("Application", descriptor); } ComputeColors(); }
public void AddRange(CommandList other) { foreach (var command in other) { internalList.Add(command); } }
public void ComputeShader3dTexture() { // Just a dumb compute shader that fills a 3D texture with the same value from a uniform multiplied by the depth. string shaderText = @" #version 450 layout(set = 0, binding = 0, rgba32f) uniform image3D TextureToFill; layout(set = 0, binding = 1) uniform FillValueBuffer { float FillValue; float Padding1; float Padding2; float Padding3; }; layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; void main() { ivec3 textureCoordinate = ivec3(gl_GlobalInvocationID.xyz); float dataToStore = FillValue * (textureCoordinate.z + 1); imageStore(TextureToFill, textureCoordinate, vec4(dataToStore)); } "; const float FillValue = 42.42f; const uint OutputTextureSize = 32; using Shader computeShader = RF.CreateFromSpirv(new ShaderDescription( ShaderStages.Compute, Encoding.ASCII.GetBytes(shaderText), "main")); using ResourceLayout computeLayout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("TextureToFill", ResourceKind.TextureReadWrite, ShaderStages.Compute), new ResourceLayoutElementDescription("FillValueBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute))); using Pipeline computePipeline = RF.CreateComputePipeline(new ComputePipelineDescription( computeShader, computeLayout, 16, 16, 1)); using DeviceBuffer fillValueBuffer = RF.CreateBuffer(new BufferDescription((uint)Marshal.SizeOf <FillValueStruct>(), BufferUsage.UniformBuffer)); // Create our output texture. using Texture computeTargetTexture = RF.CreateTexture(TextureDescription.Texture3D( OutputTextureSize, OutputTextureSize, OutputTextureSize, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.Sampled | TextureUsage.Storage)); using TextureView computeTargetTextureView = RF.CreateTextureView(computeTargetTexture); using ResourceSet computeResourceSet = RF.CreateResourceSet(new ResourceSetDescription( computeLayout, computeTargetTextureView, fillValueBuffer)); using CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.UpdateBuffer(fillValueBuffer, 0, new FillValueStruct(FillValue)); // Use the compute shader to fill the texture. cl.SetPipeline(computePipeline); cl.SetComputeResourceSet(0, computeResourceSet); const uint GroupDivisorXY = 16; cl.Dispatch(OutputTextureSize / GroupDivisorXY, OutputTextureSize / GroupDivisorXY, OutputTextureSize); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); // Read back from our texture and make sure it has been properly filled. for (uint depth = 0; depth < computeTargetTexture.Depth; depth++) { RgbaFloat expectedFillValue = new RgbaFloat(new System.Numerics.Vector4(FillValue * (depth + 1))); int notFilledCount = CountTexelsNotFilledAtDepth(GD, computeTargetTexture, expectedFillValue, depth); Assert.Equal(0, notFilledCount); } }
internal void RecreateWindowSizedResources(GraphicsDevice gd, CommandList cl) { MainSceneColorTexture?.Dispose(); MainSceneDepthTexture?.Dispose(); MainSceneResolvedColorTexture?.Dispose(); MainSceneResolvedColorView?.Dispose(); MainSceneViewResourceSet?.Dispose(); MainSceneFramebuffer?.Dispose(); DuplicatorTarget0?.Dispose(); DuplicatorTarget1?.Dispose(); DuplicatorTargetView0?.Dispose(); DuplicatorTargetView1?.Dispose(); DuplicatorTargetSet0?.Dispose(); DuplicatorTargetSet1?.Dispose(); DuplicatorFramebuffer?.Dispose(); ResourceFactory factory = gd.ResourceFactory; TextureSampleCount mainSceneSampleCountCapped = (TextureSampleCount)Math.Min( (int)gd.GetSampleCountLimit(PixelFormat.R8_G8_B8_A8_UNorm, false), (int)MainSceneSampleCount); TextureDescription mainColorDesc = new TextureDescription( gd.SwapchainFramebuffer.Width, gd.SwapchainFramebuffer.Height, 1, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled, mainSceneSampleCountCapped); MainSceneColorTexture = factory.CreateTexture(ref mainColorDesc); if (mainSceneSampleCountCapped != TextureSampleCount.Count1) { mainColorDesc.SampleCount = TextureSampleCount.Count1; MainSceneResolvedColorTexture = factory.CreateTexture(ref mainColorDesc); } else { MainSceneResolvedColorTexture = MainSceneColorTexture; } MainSceneResolvedColorView = factory.CreateTextureView(MainSceneResolvedColorTexture); MainSceneDepthTexture = factory.CreateTexture(new TextureDescription( gd.SwapchainFramebuffer.Width, gd.SwapchainFramebuffer.Height, 1, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil, mainSceneSampleCountCapped)); MainSceneFramebuffer = factory.CreateFramebuffer(new FramebufferDescription(MainSceneDepthTexture, MainSceneColorTexture)); MainSceneViewResourceSet = factory.CreateResourceSet(new ResourceSetDescription(TextureSamplerResourceLayout, MainSceneResolvedColorView, gd.PointSampler)); TextureDescription colorTargetDesc = new TextureDescription( gd.SwapchainFramebuffer.Width, gd.SwapchainFramebuffer.Height, 1, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled); DuplicatorTarget0 = factory.CreateTexture(ref colorTargetDesc); DuplicatorTargetView0 = factory.CreateTextureView(DuplicatorTarget0); DuplicatorTarget1 = factory.CreateTexture(ref colorTargetDesc); DuplicatorTargetView1 = factory.CreateTextureView(DuplicatorTarget1); DuplicatorTargetSet0 = factory.CreateResourceSet(new ResourceSetDescription(TextureSamplerResourceLayout, DuplicatorTargetView0, gd.PointSampler)); DuplicatorTargetSet1 = factory.CreateResourceSet(new ResourceSetDescription(TextureSamplerResourceLayout, DuplicatorTargetView1, gd.PointSampler)); FramebufferDescription fbDesc = new FramebufferDescription(null, DuplicatorTarget0, DuplicatorTarget1); DuplicatorFramebuffer = factory.CreateFramebuffer(ref fbDesc); }
public void FillBuffer_WithOffsets(uint srcSetMultiple, uint srcBindingMultiple, uint dstSetMultiple, uint dstBindingMultiple, bool combinedLayout) { if (!GD.Features.ComputeShader) { return; } if (!GD.Features.BufferRangeBinding && (srcSetMultiple != 0 || srcBindingMultiple != 0 || dstSetMultiple != 0 || dstBindingMultiple != 0)) { return; } Debug.Assert((GD.StructuredBufferMinOffsetAlignment % sizeof(uint)) == 0); uint valueCount = 512; uint dataSize = valueCount * sizeof(uint); uint totalSrcAlignment = GD.StructuredBufferMinOffsetAlignment * (srcSetMultiple + srcBindingMultiple); uint totalDstAlignment = GD.StructuredBufferMinOffsetAlignment * (dstSetMultiple + dstBindingMultiple); DeviceBuffer copySrc = RF.CreateBuffer( new BufferDescription(totalSrcAlignment + dataSize, BufferUsage.StructuredBufferReadOnly, sizeof(uint))); DeviceBuffer copyDst = RF.CreateBuffer( new BufferDescription(totalDstAlignment + dataSize, BufferUsage.StructuredBufferReadWrite, sizeof(uint))); ResourceLayout[] layouts; ResourceSet[] sets; DeviceBufferRange srcRange = new DeviceBufferRange(copySrc, srcSetMultiple * GD.StructuredBufferMinOffsetAlignment, dataSize); DeviceBufferRange dstRange = new DeviceBufferRange(copyDst, dstSetMultiple * GD.StructuredBufferMinOffsetAlignment, dataSize); if (combinedLayout) { layouts = new[] { RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription( "CopySrc", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute, ResourceLayoutElementOptions.DynamicBinding), new ResourceLayoutElementDescription( "CopyDst", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute, ResourceLayoutElementOptions.DynamicBinding))) }; sets = new[] { RF.CreateResourceSet(new ResourceSetDescription(layouts[0], srcRange, dstRange)) }; } else { layouts = new[] { RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription( "CopySrc", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute, ResourceLayoutElementOptions.DynamicBinding))), RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription( "CopyDst", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute, ResourceLayoutElementOptions.DynamicBinding))) }; sets = new[] { RF.CreateResourceSet(new ResourceSetDescription(layouts[0], srcRange)), RF.CreateResourceSet(new ResourceSetDescription(layouts[1], dstRange)), }; } Pipeline pipeline = RF.CreateComputePipeline(new ComputePipelineDescription( TestShaders.LoadCompute(RF, combinedLayout ? "FillBuffer" : "FillBuffer_SeparateLayout"), layouts, 1, 1, 1)); uint[] srcData = Enumerable.Range(0, (int)copySrc.SizeInBytes / sizeof(uint)).Select(i => (uint)i).ToArray(); GD.UpdateBuffer(copySrc, 0, srcData); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetPipeline(pipeline); if (combinedLayout) { uint[] offsets = new[] { srcBindingMultiple *GD.StructuredBufferMinOffsetAlignment, dstBindingMultiple *GD.StructuredBufferMinOffsetAlignment }; cl.SetComputeResourceSet(0, sets[0], offsets); } else { uint offset = srcBindingMultiple * GD.StructuredBufferMinOffsetAlignment; cl.SetComputeResourceSet(0, sets[0], 1, ref offset); offset = dstBindingMultiple * GD.StructuredBufferMinOffsetAlignment; cl.SetComputeResourceSet(1, sets[1], 1, ref offset); } cl.Dispatch(512, 1, 1); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); DeviceBuffer readback = GetReadback(copyDst); MappedResourceView <uint> readView = GD.Map <uint>(readback, MapMode.Read); for (uint i = 0; i < valueCount; i++) { uint srcIndex = totalSrcAlignment / sizeof(uint) + i; uint expected = srcData[(int)srcIndex]; uint dstIndex = totalDstAlignment / sizeof(uint) + i; uint actual = readView[dstIndex]; Assert.Equal(expected, actual); } GD.Unmap(readback); }
protected override Glyph GetGlyph(CommandList commandList, char character, ref Vector2 fontSize, bool dumb) { Glyph glyph = null; if (!CharacterToGlyph.ContainsKey(character)) Logger.Warning("Character '{0}' is not available in the static font character map", character); else glyph = CharacterToGlyph[character]; return glyph; }
/// <summary> /// Generates an index mapping with the specified vertex elements. /// If no vertex elements are specified, use the whole vertex. /// </summary> /// <param name="vertexBufferBinding">The vertex buffer binding.</param> /// <param name="usages">The vertex element usages to consider.</param> /// <returns></returns> public static unsafe IndexMappingResult GenerateIndexMapping(this VertexBufferBinding vertexBufferBinding, CommandList commandList, params string[] usages) { var bufferData = vertexBufferBinding.Buffer.GetDataSafe(commandList); var vertexStride = vertexBufferBinding.Declaration.VertexStride; var vertexCount = vertexBufferBinding.Count; var activeBytes = stackalloc byte[vertexStride]; var vertexMapping = new List <int>(); var indexMapping = new int[vertexCount]; var mapping = new Dictionary <VertexKey, int>(new VertexKeyEqualityComparer(activeBytes, vertexStride)); // Create a "mask" of part of the vertices that will be used // TODO: Use bit packing? for (int i = 0; i < vertexBufferBinding.Declaration.VertexStride; ++i) { activeBytes[i] = (byte)(usages.Length == 0 ? 1 : 0); } foreach (var vertexElement in vertexBufferBinding.Declaration.EnumerateWithOffsets()) { if (usages.Contains(vertexElement.VertexElement.SemanticAsText)) { for (int i = 0; i < vertexElement.Size; ++i) { activeBytes[vertexElement.Offset + i] = 1; } } } // Generate index buffer fixed(byte *bufferPointerStart = &bufferData[vertexBufferBinding.Offset]) { var bufferPointer = bufferPointerStart; for (int i = 0; i < vertexCount; ++i) { // Create VertexKey (will generate hash) var vertexKey = new VertexKey(bufferPointer, activeBytes, vertexStride); // Get or create new index int currentIndex; if (!mapping.TryGetValue(vertexKey, out currentIndex)) { currentIndex = vertexMapping.Count; mapping.Add(vertexKey, currentIndex); vertexMapping.Add(i); } // Assign index in result buffer indexMapping[i] = currentIndex; bufferPointer += vertexStride; } } return(new IndexMappingResult { Vertices = vertexMapping.ToArray(), Indices = indexMapping }); }
internal void LazyInitialize() { if(Context == null) { Context = new DeviceContext(MyRender11.Device); //MyRenderContextPool.m_intialized.Enqueue(Context); } State.Clear(); Stats.Clear(); m_finished = false; m_joined = false; m_commandList = null; }
public abstract void RenderMirrorTexture(CommandList cl, Framebuffer fb, MirrorTextureEyeSource source);
internal CommandList GrabCommandList() { Debug.Assert(!(m_finished && m_commandList == null), "you grabbed that list already"); Finish(); var result = m_commandList; m_commandList = null; return result; }
public void BasicCompute() { if (!GD.Features.ComputeShader) { return; } ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute), new ResourceLayoutElementDescription("Source", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute), new ResourceLayoutElementDescription("Destination", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute))); uint width = 1024; uint height = 1024; DeviceBuffer paramsBuffer = RF.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <BasicComputeTestParams>(), BufferUsage.UniformBuffer)); DeviceBuffer sourceBuffer = RF.CreateBuffer(new BufferDescription(width * height * 4, BufferUsage.StructuredBufferReadWrite, 4)); DeviceBuffer destinationBuffer = RF.CreateBuffer(new BufferDescription(width * height * 4, BufferUsage.StructuredBufferReadWrite, 4)); GD.UpdateBuffer(paramsBuffer, 0, new BasicComputeTestParams { Width = width, Height = height }); float[] sourceData = new float[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int index = y * (int)width + x; sourceData[index] = index; } } GD.UpdateBuffer(sourceBuffer, 0, sourceData); ResourceSet rs = RF.CreateResourceSet(new ResourceSetDescription(layout, paramsBuffer, sourceBuffer, destinationBuffer)); Pipeline pipeline = RF.CreateComputePipeline(new ComputePipelineDescription( TestShaders.LoadCompute(RF, "BasicComputeTest"), layout, 16, 16, 1)); CommandList cl = RF.CreateCommandList(); cl.Begin(); cl.SetPipeline(pipeline); cl.SetComputeResourceSet(0, rs); cl.Dispatch(width / 16, width / 16, 1); cl.End(); GD.SubmitCommands(cl); GD.WaitForIdle(); DeviceBuffer sourceReadback = GetReadback(sourceBuffer); DeviceBuffer destinationReadback = GetReadback(destinationBuffer); MappedResourceView <float> sourceReadView = GD.Map <float>(sourceReadback, MapMode.Read); MappedResourceView <float> destinationReadView = GD.Map <float>(destinationReadback, MapMode.Read); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int index = y * (int)width + x; Assert.Equal(2 * sourceData[index], sourceReadView[index]); Assert.Equal(sourceData[index], destinationReadView[index]); } } GD.Unmap(sourceReadback); GD.Unmap(destinationReadback); }
public virtual void CreateDeviceObjects(GraphicsDevice gd, CommandList cl, SceneContext sc) { ResourceFactory factory = gd.ResourceFactory; ProjectionMatrixBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); ViewMatrixBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightViewProjectionBuffer0 = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightViewProjectionBuffer0.Name = "LightViewProjectionBuffer0"; LightViewProjectionBuffer1 = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightViewProjectionBuffer1.Name = "LightViewProjectionBuffer1"; LightViewProjectionBuffer2 = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightViewProjectionBuffer2.Name = "LightViewProjectionBuffer2"; DepthLimitsBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <DepthCascadeLimits>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); LightInfoBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <DirectionalLightInfo>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); CameraInfoBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <CameraInfo>(), BufferUsage.UniformBuffer | BufferUsage.Dynamic)); if (Camera != null) { UpdateCameraBuffers(cl); } PointLightsBuffer = factory.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <PointLightsInfo.Blittable>(), BufferUsage.UniformBuffer)); PointLightsInfo pli = new PointLightsInfo(); pli.NumActiveLights = 4; pli.PointLights = new PointLightInfo[4] { new PointLightInfo { Color = new Vector3(1f, 1f, 1f), Position = new Vector3(-50, 5, 0), Range = 75f }, new PointLightInfo { Color = new Vector3(1f, .75f, .9f), Position = new Vector3(0, 5, 0), Range = 100f }, new PointLightInfo { Color = new Vector3(1f, 1f, 0.6f), Position = new Vector3(50, 5, 0), Range = 40f }, new PointLightInfo { Color = new Vector3(0.75f, 0.75f, 1f), Position = new Vector3(25, 5, 45), Range = 150f }, }; cl.UpdateBuffer(PointLightsBuffer, 0, pli.GetBlittable()); TextureSamplerResourceLayout = factory.CreateResourceLayout(new ResourceLayoutDescription( new ResourceLayoutElementDescription("SourceTexture", ResourceKind.TextureReadOnly, ShaderStages.Fragment), new ResourceLayoutElementDescription("SourceSampler", ResourceKind.Sampler, ShaderStages.Fragment))); uint ReflectionMapSize = 2048; ReflectionColorTexture = factory.CreateTexture(new TextureDescription(ReflectionMapSize, ReflectionMapSize, 1, 1, 1, PixelFormat.R8_G8_B8_A8_UNorm, TextureUsage.RenderTarget | TextureUsage.Sampled)); ReflectionDepthTexture = factory.CreateTexture(new TextureDescription(ReflectionMapSize, ReflectionMapSize, 1, 1, 1, PixelFormat.R16_UNorm, TextureUsage.DepthStencil)); ReflectionColorView = factory.CreateTextureView(ReflectionColorTexture); ReflectionFramebuffer = factory.CreateFramebuffer(new FramebufferDescription(ReflectionDepthTexture, ReflectionColorTexture)); ReflectionViewProjBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic)); MirrorClipPlaneBuffer = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer)); gd.UpdateBuffer(MirrorClipPlaneBuffer, 0, new ClipPlaneInfo(MirrorMesh.Plane, true)); NoClipPlaneBuffer = factory.CreateBuffer(new BufferDescription(32, BufferUsage.UniformBuffer)); gd.UpdateBuffer(NoClipPlaneBuffer, 0, new ClipPlaneInfo()); RecreateWindowSizedResources(gd, cl); ShadowMaps.CreateDeviceResources(gd); }
public void SNIPE_InitCommands() { // GA CommandList.Add(new Command("ga", 0, Command.Behaviour.Normal, (sender, arguments, optarg) => { if (Call <string>("getdvar", "g_gametype") == "infect" && sender.GetTeam() == "axis") { WriteChatToPlayer(sender, "I like the way you're thinking, but nope."); return; } CMD_GiveMaxAmmo(sender); WriteChatToPlayer(sender, Command.GetString("ga", "message")); })); // FT // FILMTWEAK CommandList.Add(new Command("ft", 1, Command.Behaviour.Normal, (sender, arguments, optarg) => { CMD_applyfilmtweak(sender, arguments[0]); WriteChatToPlayer(sender, Command.GetString("ft", "message").Format(new Dictionary <string, string>() { { "<ft>", arguments[0] }, })); })); // KNIFE CommandList.Add(new Command("knife", 1, Command.Behaviour.Normal, (sender, arguments, optarg) => { bool enabled = UTILS_ParseBool(arguments[0]); CMD_knife(enabled); if (enabled) { WriteChatToAll(Command.GetString("knife", "message_on")); } else { WriteChatToAll(Command.GetString("knife", "message_off")); } })); // LETMEHARDSCOPE CommandList.Add(new Command("letmehardscope", 1, Command.Behaviour.Normal, (sender, arguments, optarg) => { bool state = UTILS_ParseBool(arguments[0]); if (state) { sender.SetField("letmehardscope", 1); WriteChatToPlayer(sender, Command.GetString("letmehardscope", "message_on")); } else { sender.SetField("letmehardscope", 0); WriteChatToPlayer(sender, Command.GetString("letmehardscope", "message_off")); } })); CommandList.Add(new Command("fx", 1, Command.Behaviour.Normal, (sender, arguments, optarg) => { bool state = UTILS_ParseBool(arguments[0]); if (state) { sender.SetClientDvar("fx_draw", "0"); sender.SetClientDvar("clientSideEffects", "0"); WriteChatToPlayer(sender, Command.GetString("fx", "message_on")); } else { sender.SetClientDvar("fx_draw", "1"); sender.SetClientDvar("clientSideEffects", "1"); WriteChatToPlayer(sender, Command.GetString("fx", "message_off")); } })); }
public void Render(RenderContext context, IPipeline pipeline, IViewport viewport, CommandList cl, ILocation locationObject) { var groupLocation = (GroupLocation)locationObject; var buffer = groupLocation.Builder; var i = groupLocation.Index; var bg = groupLocation.Group; cl.SetVertexBuffer(0, buffer.VertexBuffers[i]); cl.SetIndexBuffer(buffer.IndexBuffers[i], IndexFormat.UInt32); pipeline.Bind(context, cl, bg.Binding); buffer.IndirectBuffers[i].DrawIndexed(cl, bg.Offset * IndSize, bg.Count, 20); }
public void RenderShadowMap( Scene3D scene, GraphicsDevice graphicsDevice, CommandList commandList, Action <Framebuffer, BoundingFrustum> drawSceneCallback) { // TODO: Use terrain light for terrain self-shadowing? var light = scene.Lighting.CurrentLightingConfiguration.ObjectLightsPS.Light0; // Calculate size of shadow map. var shadowMapSize = scene.Shadows.ShadowMapSize; var numCascades = (uint)scene.Shadows.ShadowMapCascades; if (_shadowData != null && _shadowData.ShadowMap != null && (_shadowData.ShadowMap.Width != shadowMapSize || _shadowData.ShadowMap.Height != shadowMapSize || _shadowData.NearPlaneDistance != scene.Camera.NearPlaneDistance || _shadowData.FarPlaneDistance != scene.Camera.FarPlaneDistance || _shadowData.NumSplits != numCascades)) { RemoveAndDispose(ref _shadowData); RemoveAndDispose(ref _resourceSet); } if (_shadowData == null) { _shadowData = AddDisposable(new ShadowData( numCascades, scene.Camera.NearPlaneDistance, scene.Camera.FarPlaneDistance, shadowMapSize, graphicsDevice)); _resourceSet = AddDisposable(graphicsDevice.ResourceFactory.CreateResourceSet( new ResourceSetDescription( _globalShaderResources.GlobalShadowResourceLayout, _shadowConstantsPSBuffer.Buffer, _shadowData.ShadowMap, _globalShaderResources.ShadowSampler))); } if (scene.Shadows.ShadowsType != ShadowsType.None) { _shadowFrustumCalculator.CalculateShadowData( light, scene.Camera, _shadowData, scene.Shadows); _shadowConstants.Set(numCascades, scene.Shadows, _shadowData); // Render scene geometry to each split of the cascade. for (var splitIndex = 0; splitIndex < _shadowData.NumSplits; splitIndex++) { _lightFrustum.Matrix = _shadowData.ShadowCameraViewProjections[splitIndex]; drawSceneCallback( _shadowData.ShadowMapFramebuffers[splitIndex], _lightFrustum); } } else { _shadowConstants.ShadowsType = ShadowsType.None; } _shadowConstantsPSBuffer.Value = _shadowConstants; _shadowConstantsPSBuffer.Update(commandList); }
public void AfterEngineInit() { // Basics. { var deviceDesc = new Device.Descriptor {DebugDevice = true}; renderDevice = new ClearSight.RendererDX12.Device(ref deviceDesc, ClearSight.RendererDX12.Device.FeatureLevel.Level_11_0); var descCQ = new CommandQueue.Descriptor() {Type = CommandListType.Graphics}; commandQueue = renderDevice.Create(ref descCQ); var wih = new WindowInteropHelper(window); var swapChainDesc = new SwapChain.Descriptor() { AssociatedGraphicsQueue = commandQueue, MaxFramesInFlight = 3, BufferCount = 3, Width = (uint) window.Width, Height = (uint) window.Height, Format = Format.R8G8B8A8_UNorm, SampleCount = 1, SampleQuality = 0, WindowHandle = wih.Handle, Fullscreen = false }; swapChain = renderDevice.Create(ref swapChainDesc); var commandListDesc = new CommandList.Descriptor() { Type = CommandListType.Graphics, AllocationPolicy = new CommandListInFlightFrameAllocationPolicy(CommandListType.Graphics, swapChain) }; commandList = renderDevice.Create(ref commandListDesc); } // Render targets. { var descHeapDesc = new DescriptorHeap.Descriptor() { Type = DescriptorHeap.Descriptor.ResourceDescriptorType.RenderTarget, NumResourceDescriptors = swapChain.Desc.BufferCount }; descHeapRenderTargets = renderDevice.Create(ref descHeapDesc); var rtvViewDesc = new RenderTargetViewDescription() { Format = swapChain.Desc.Format, Dimension = Dimension.Texture2D, Texture = new TextureSubresourceDesc(mipSlice: 0) }; for (uint i = 0; i < swapChain.Desc.BufferCount; ++i) { renderDevice.CreateRenderTargetView(descHeapRenderTargets, i, swapChain.BackbufferResources[i], ref rtvViewDesc); } } }
public IEnumerable <IRenderable> UpdatePerFrameResources(GraphicsDevice gd, CommandList cl, SceneContext sc, IEnumerable <IRenderable> renderables) => renderables;
private static bool ValidateCommand(ConsoleCommand command, CommandList commands, out ConsoleExecutingAssembly instance, out Dictionary<string, ConsoleExecutingMethod> methodDictionary) { instance = null; methodDictionary = null; // Validate the command name: var found = false; foreach (var key in commands.Keys.Where(key => key.Namespace == command.LibraryClassName)) { found = true; instance = key; methodDictionary = commands[key]; break; } if (!found) { return false; } if (!methodDictionary.ContainsKey(command.Name)) { var newCommand = char.ToUpperInvariant(command.Name[0]) + command.Name.Substring(1); if (!methodDictionary.ContainsKey(newCommand)) { return false; } command.Name = char.ToUpperInvariant(command.Name[0]) + command.Name.Substring(1); } return true; }
public override void Run() { #region Create renderers // Note: the renderers take care of creating their own // device resources and listen for DeviceManager.OnInitialize #region Initialize MeshRenderer instances // Create and initialize the mesh renderer var loadedMesh = Common.Mesh.LoadFromFile("Scene.cmo"); List <MeshRenderer> meshes = new List <MeshRenderer>(); meshes.AddRange((from mesh in loadedMesh select ToDispose(new MeshRenderer(mesh)))); // We will support a envmap for each mesh that contains "reflector" in its name List <DualParaboloidMap> envMaps = new List <DualParaboloidMap>(); // We will rotate any meshes that contains "rotate" in its name List <MeshRenderer> rotateMeshes = new List <MeshRenderer>(); // We will generate meshRows * meshColumns of any mesh that contains "replicate" in its name int meshRows = 10; int meshColumns = 10; // Define an action to initialize our meshes so that we can // dynamically change the number of reflective surfaces and // replicated meshes Action createMeshes = () => { // Clear context states, ensures we don't have // any of the resources we are going to release // assigned to the pipeline. DeviceManager.Direct3DContext.ClearState(); if (contextList != null) { foreach (var context in contextList) { context.ClearState(); } } // Remove meshes foreach (var mesh in meshes) { mesh.Dispose(); } meshes.Clear(); // Remove environment maps foreach (var envMap in envMaps) { envMap.Dispose(); } envMaps.Clear(); // Create non-replicated MeshRenderer instances meshes.AddRange(from mesh in loadedMesh where !((mesh.Name ?? "").ToLower().Contains("replicate")) select ToDispose(new MeshRenderer(mesh))); #region Create replicated meshes // Add the same mesh multiple times, separate by the combined extent var replicatedMeshes = (from mesh in loadedMesh where (mesh.Name ?? "").ToLower().Contains("replicate") select mesh).ToArray(); if (replicatedMeshes.Length > 0) { var minExtent = (from mesh in replicatedMeshes orderby new { mesh.Extent.Min.X, mesh.Extent.Min.Z } select mesh.Extent).First(); var maxExtent = (from mesh in replicatedMeshes orderby new { mesh.Extent.Max.X, mesh.Extent.Max.Z } descending select mesh.Extent).First(); var extentDiff = (maxExtent.Max - minExtent.Min); for (int x = -(meshColumns / 2); x < (meshColumns / 2); x++) { for (int z = -(meshRows / 2); z < (meshRows / 2); z++) { var meshGroup = (from mesh in replicatedMeshes where (mesh.Name ?? "").ToLower().Contains("replicate") select ToDispose(new MeshRenderer(mesh))).ToList(); // Reposition based on width/depth of combined extent foreach (var m in meshGroup) { m.World.TranslationVector = new Vector3(m.Mesh.Extent.Center.X + extentDiff.X * x, m.Mesh.Extent.Min.Y, m.Mesh.Extent.Center.Z + extentDiff.Z * z); } meshes.AddRange(meshGroup); } } } #endregion #region Create reflective meshes // Create reflections where necessary and add rotation meshes int reflectorCount = 0; meshes.ForEach(m => { var name = (m.Mesh.Name ?? "").ToLower(); if (name.Contains("reflector") && reflectorCount < maxReflectors) { reflectorCount++; var envMap = ToDispose(new DualParaboloidMap(512)); envMap.Reflector = m; envMap.Initialize(this); m.EnvironmentMap = envMap; envMaps.Add(envMap); } if (name.Contains("rotate")) { rotateMeshes.Add(m); } m.Initialize(this); }); #endregion // Initialize each mesh meshes.ForEach(m => m.Initialize(this)); }; createMeshes(); // Set the first animation as the current animation and start clock meshes.ForEach(m => { if (m.Mesh.Animations != null && m.Mesh.Animations.Any()) { m.CurrentAnimation = m.Mesh.Animations.First().Value; } m.Clock.Start(); }); // Create the overall mesh World matrix var meshWorld = Matrix.Identity; #endregion // Create and initialize a Direct2D FPS text renderer var fps = ToDispose(new Common.FpsRenderer("Calibri", Color.CornflowerBlue, new Point(8, 8), 16)); fps.Initialize(this); // Create and initialize a general purpose Direct2D text renderer // This will display some instructions and the current view and rotation offsets var textRenderer = ToDispose(new Common.TextRenderer("Calibri", Color.CornflowerBlue, new Point(8, 40), 12)); textRenderer.Initialize(this); #endregion // Initialize the world matrix var worldMatrix = Matrix.Identity; // Set the camera position slightly behind (z) var cameraPosition = new Vector3(0, 1, 2); var cameraTarget = Vector3.Zero; // Looking at the origin 0,0,0 var cameraUp = Vector3.UnitY; // Y+ is Up // Prepare matrices // Create the view matrix from our camera position, look target and up direction var viewMatrix = Matrix.LookAtRH(cameraPosition, cameraTarget, cameraUp); viewMatrix.TranslationVector += new Vector3(0, -0.98f, 0); // Create the projection matrix /* FoV 60degrees = Pi/3 radians */ // Aspect ratio (based on window size), Near clip, Far clip var projectionMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 3f, Width / (float)Height, 0.1f, 100f); // Maintain the correct aspect ratio on resize Window.Resize += (s, e) => { projectionMatrix = Matrix.PerspectiveFovRH((float)Math.PI / 3f, Width / (float)Height, 0.1f, 100f); }; #region Rotation and window event handlers // Create a rotation vector to keep track of the rotation // around each of the axes var rotation = new Vector3(0.0f, 0.0f, 0.0f); // We will call this action to update text // for the text renderer Action updateText = () => { textRenderer.Text = String.Format( "\nPause rotation: P" + "\nThreads: {0} (+/-)" + "\nReflectors: {1} (Shift-Up/Down)" + "\nCPU load: {2} matrix ops (Shift +/-)" + "\nRotating meshes: {3} (Up/Down, Left/Right)" , threadCount, maxReflectors, additionalCPULoad, meshRows * meshColumns); }; Dictionary <Keys, bool> keyToggles = new Dictionary <Keys, bool>(); keyToggles[Keys.Z] = false; keyToggles[Keys.F] = false; // Support keyboard/mouse input to rotate or move camera view var moveFactor = 0.02f; // how much to change on each keypress var shiftKey = false; var ctrlKey = false; var background = Color.White; Window.KeyDown += (s, e) => { var context = DeviceManager.Direct3DContext; shiftKey = e.Shift; ctrlKey = e.Control; switch (e.KeyCode) { // WASD -> pans view case Keys.A: viewMatrix.TranslationVector += new Vector3(moveFactor * 2, 0f, 0f); break; case Keys.D: viewMatrix.TranslationVector -= new Vector3(moveFactor * 2, 0f, 0f); break; case Keys.S: if (shiftKey) { viewMatrix.TranslationVector += new Vector3(0f, moveFactor * 2, 0f); } else { viewMatrix.TranslationVector -= new Vector3(0f, 0f, 1) * moveFactor * 2; } break; case Keys.W: if (shiftKey) { viewMatrix.TranslationVector -= new Vector3(0f, moveFactor * 2, 0f); } else { viewMatrix.TranslationVector += new Vector3(0f, 0f, 1) * moveFactor * 2; } break; // Up/Down and Left/Right - rotates around X / Y respectively // (Mouse wheel rotates around Z) //case Keys.Down: // worldMatrix *= Matrix.RotationX(moveFactor); // rotation += new Vector3(moveFactor, 0f, 0f); // break; //case Keys.Up: // worldMatrix *= Matrix.RotationX(-moveFactor); // rotation -= new Vector3(moveFactor, 0f, 0f); // break; //case Keys.Left: // worldMatrix *= Matrix.RotationY(moveFactor); // rotation += new Vector3(0f, moveFactor, 0f); // break; //case Keys.Right: // worldMatrix *= Matrix.RotationY(-moveFactor); // rotation -= new Vector3(0f, moveFactor, 0f); // break; case Keys.T: fps.Show = !fps.Show; textRenderer.Show = !textRenderer.Show; break; case Keys.B: if (background == Color.White) { background = new Color(30, 30, 34); } else { background = Color.White; } break; case Keys.P: // Pause or resume mesh animation meshes.ForEach(m => { if (m.Clock.IsRunning) { m.Clock.Stop(); } else { m.Clock.Start(); } }); break; case Keys.X: // To test for correct resource recreation // Simulate device reset or lost. System.Diagnostics.Debug.WriteLine(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()); DeviceManager.Initialize(DeviceManager.Dpi); System.Diagnostics.Debug.WriteLine(SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()); break; //case Keys.Z: // keyToggles[Keys.Z] = !keyToggles[Keys.Z]; // if (keyToggles[Keys.Z]) // { // context.PixelShader.Set(depthPixelShader); // } // else // { // context.PixelShader.Set(pixelShader); // } // break; case Keys.F: keyToggles[Keys.F] = !keyToggles[Keys.F]; RasterizerStateDescription rasterDesc; if (context.Rasterizer.State != null) { rasterDesc = context.Rasterizer.State.Description; } else { rasterDesc = new RasterizerStateDescription() { CullMode = CullMode.Back, FillMode = FillMode.Solid } }; if (keyToggles[Keys.F]) { rasterDesc.FillMode = FillMode.Wireframe; rasterizerState = ToDispose(new RasterizerState(context.Device, rasterDesc)); } else { rasterDesc.FillMode = FillMode.Solid; rasterizerState = ToDispose(new RasterizerState(context.Device, rasterDesc)); } break; //case Keys.D1: // context.PixelShader.Set(pixelShader); // break; //case Keys.D2: // context.PixelShader.Set(lambertShader); // break; //case Keys.D3: // context.PixelShader.Set(phongShader); // break; //case Keys.D4: // context.PixelShader.Set(blinnPhongShader); // break; //case Keys.D5: // context.PixelShader.Set(simpleUVShader); // break; //case Keys.D6: // context.PixelShader.Set(lambertUVShader); // break; //case Keys.D7: // context.PixelShader.Set(phongUVShader); // break; //case Keys.D8: // context.PixelShader.Set(blinnPhongUVShader); // break; } updateText(); }; Window.KeyUp += (s, e) => { // Clear the shift/ctrl keys so they aren't sticky if (e.KeyCode == Keys.ShiftKey) { shiftKey = false; } if (e.KeyCode == Keys.ControlKey) { ctrlKey = false; } }; Window.MouseWheel += (s, e) => { if (shiftKey) { // Zoom in/out viewMatrix.TranslationVector += new Vector3(0f, 0f, (e.Delta / 120f) * moveFactor * 2); } else { // rotate around Z-axis viewMatrix *= Matrix.RotationZ((e.Delta / 120f) * moveFactor); rotation += new Vector3(0f, 0f, (e.Delta / 120f) * moveFactor); } updateText(); }; var lastX = 0; var lastY = 0; Window.MouseDown += (s, e) => { if (e.Button == MouseButtons.Left) { lastX = e.X; lastY = e.Y; } }; Window.MouseMove += (s, e) => { if (e.Button == MouseButtons.Left) { var yRotate = lastX - e.X; var xRotate = lastY - e.Y; lastY = e.Y; lastX = e.X; // Mouse move changes viewMatrix *= Matrix.RotationX(-xRotate * moveFactor); viewMatrix *= Matrix.RotationY(-yRotate * moveFactor); updateText(); } }; // Display instructions with initial values updateText(); #endregion var clock = new System.Diagnostics.Stopwatch(); clock.Start(); // Setup the deferred contexts SetupContextList(); #region Render loop // Whether or not to reinitialize meshes bool initializeMesh = false; // Define additional key handlers for controlling the // number of threads, reflectors, and replicated meshes #region Dynamic Cube map and threading KeyDown handlers Window.KeyDown += (s, e) => { switch (e.KeyCode) { case Keys.Up: if (shiftKey) { maxReflectors++; } else { meshRows += 2; } initializeMesh = true; break; case Keys.Down: if (shiftKey) { maxReflectors = Math.Max(0, maxReflectors - 1); } else { meshRows = Math.Max(2, meshRows - 2); } initializeMesh = true; break; case Keys.Right: meshColumns += 2; initializeMesh = true; break; case Keys.Left: meshColumns = Math.Max(2, meshColumns - 2); initializeMesh = true; break; case Keys.Add: if (shiftKey) { additionalCPULoad += 100; } else { threadCount++; } break; case Keys.Subtract: if (shiftKey) { additionalCPULoad = Math.Max(0, additionalCPULoad - 100); } else { threadCount = Math.Max(1, threadCount - 1); } break; case Keys.Enter: if (keyToggles.ContainsKey(Keys.Enter)) { keyToggles[Keys.Enter] = !keyToggles[Keys.Enter]; } else { keyToggles[Keys.Enter] = true; } break; default: break; } updateText(); }; #endregion #region Render mesh group // Action for rendering a group of meshes for a // context (based on number of available contexts) Action <int, DeviceContext, Matrix, Matrix> renderMeshGroup = (contextIndex, renderContext, view, projection) => { var viewProjection = view * projection; // Determine the meshes to render for this context int batchSize = (int)Math.Floor((double)meshes.Count / contextList.Length); int startIndex = batchSize * contextIndex; int endIndex = Math.Min(startIndex + batchSize, meshes.Count - 1); // If this is the last context include whatever remains to be // rendered due to the rounding above. if (contextIndex == contextList.Length - 1) { endIndex = meshes.Count - 1; } // Loop over the meshes for this context and render them var perObject = new ConstantBuffers.PerObject(); for (var i = startIndex; i <= endIndex; i++) { // Simulate additional CPU load for (var j = 0; j < additionalCPULoad; j++) { viewProjection = Matrix.Multiply(view, projection); } // Retrieve current mesh var m = meshes[i]; // Check if this is a rotating mesh if (rotateMeshes.Contains(m)) { var rotate = Matrix.RotationAxis(Vector3.UnitY, m.Clock.ElapsedMilliseconds / 1000.0f); perObject.World = m.World * rotate * worldMatrix; } else { perObject.World = m.World * worldMatrix; } // Update perObject constant buffer perObject.WorldInverseTranspose = Matrix.Transpose(Matrix.Invert(perObject.World)); perObject.WorldViewProjection = perObject.World * viewProjection; perObject.Transpose(); renderContext.UpdateSubresource(ref perObject, perObjectBuffer); // Provide the material and armature constant buffer to the mesh renderer m.PerArmatureBuffer = perArmatureBuffer; m.PerMaterialBuffer = perMaterialBuffer; // Render the mesh using the provided DeviceContext m.Render(renderContext); } }; #endregion #region Render scene // Action for rendering the entire scene Action <DeviceContext, Matrix, Matrix, RenderTargetView, DepthStencilView, DualParaboloidMap> renderScene = (context, view, projection, rtv, dsv, envMap) => { // We must initialize the context every time we render // the scene as we are changing the state depending on // whether we are rendering the envmaps or final scene InitializeContext(context, false); // We always need the immediate context // Note: the passed in context will normally be the immediate context // however it is possible to run this method threaded also. var immediateContext = this.DeviceManager.Direct3DDevice.ImmediateContext; // Clear depth stencil view context.ClearDepthStencilView(dsv, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0); // Clear render target view context.ClearRenderTargetView(rtv, background); // Create viewProjection matrix var viewProjection = Matrix.Multiply(view, projection); // Extract camera position from view var camPosition = Matrix.Transpose(Matrix.Invert(view)).Column4; cameraPosition = new Vector3(camPosition.X, camPosition.Y, camPosition.Z); // Setup the per frame constant buffer var perFrame = new ConstantBuffers.PerFrame(); perFrame.Light.Color = new Color(0.9f, 0.9f, 0.9f, 1.0f); var lightDir = Vector3.Transform(new Vector3(-1f, -1f, -1f), worldMatrix); perFrame.Light.Direction = new Vector3(lightDir.X, lightDir.Y, lightDir.Z); perFrame.CameraPosition = cameraPosition; context.UpdateSubresource(ref perFrame, perFrameBuffer); // Render each object // Prepare the default per material constant buffer var perMaterial = new ConstantBuffers.PerMaterial(); perMaterial.Ambient = new Color4(0.2f); perMaterial.Diffuse = Color.White; perMaterial.Emissive = new Color4(0); perMaterial.Specular = Color.White; perMaterial.SpecularPower = 20f; context.UpdateSubresource(ref perMaterial, perMaterialBuffer); // ----------Render meshes------------ if (contextList.Length == 1) { // If there is only one context available there is no need to // generate command lists and execute them so just render the // mesh directly on the current context (which may or may // not be an immediate context depending on the caller). renderMeshGroup(0, context, view, projection); } else { // There are multiple contexts therefore // we are using deferred contexts. Prepare a // separate thread for each available context // and render a group of meshes on each. Task[] renderTasks = new Task[contextList.Length]; CommandList[] commands = new CommandList[contextList.Length]; var viewports = context.Rasterizer.GetViewports(); for (var i = 0; i < contextList.Length; i++) { // Must store the iteration value in another variable // or each task action will use the last iteration value. var contextIndex = i; // Create task to run on new thread from ThreadPool renderTasks[i] = Task.Run(() => { // Retrieve context for this thread var renderContext = contextList[contextIndex]; // Initialize the context state InitializeContext(renderContext, false); // Set the render targets and viewport renderContext.OutputMerger.SetRenderTargets(dsv, rtv); renderContext.Rasterizer.SetViewports(viewports); // If we are rendering for an env map we must set the // per environment map buffer. if (envMap != null) { renderContext.VertexShader.SetConstantBuffer(4, envMap.PerEnvMapBuffer); renderContext.PixelShader.SetConstantBuffer(4, envMap.PerEnvMapBuffer); } // Render logic renderMeshGroup(contextIndex, renderContext, view, projection); // Create the command list if (renderContext.TypeInfo == DeviceContextType.Deferred) { commands[contextIndex] = renderContext.FinishCommandList(false); } }); } // Wait for all the tasks to complete Task.WaitAll(renderTasks); // Replay the command lists on the immediate context for (var i = 0; i < contextList.Length; i++) { if (contextList[i].TypeInfo == DeviceContextType.Deferred && commands[i] != null) { immediateContext.ExecuteCommandList(commands[i], false); // Clean up command list commands[i].Dispose(); commands[i] = null; } } } }; #endregion long frameCount = 0; int lastThreadCount = threadCount; keyToggles[Keys.Enter] = false; // Create and run the render loop RenderLoop.Run(Window, () => { // Allow dynamic changes to number of reflectors and replications if (initializeMesh) { initializeMesh = false; createMeshes(); } if (keyToggles[Keys.Enter]) { // Export the paraboloid maps var i = 0; foreach (var item in envMaps) { using (var tex = item.EnvMapSRV.ResourceAs <Texture2D>()) { for (var j = 0; j < tex.Description.ArraySize; j++) { CopyTexture.SaveToFile(DeviceManager, tex, String.Format("DualMap{0}_{1}.png", i, j), null, tex.Description.MipLevels * j); } i++; } } keyToggles[Keys.Enter] = false; } // Allow dynamic chnages to the number of threads to use if (lastThreadCount != threadCount) { SetupContextList(); lastThreadCount = threadCount; } // Start of frame: frameCount++; // Retrieve immediate context var context = DeviceManager.Direct3DContext; //if (frameCount % 3 == 1) // to update envmap once every third frame //{ #region Update environment maps // Update each of the environment maps activeVertexShader = envMapVSShader; activeGeometryShader = envMapGSShader; activePixelShader = envMapPSShader; // Render the scene from the perspective of each of the environment maps foreach (var envMap in envMaps) { var mesh = envMap.Reflector as MeshRenderer; if (mesh != null) { // Calculate view point for reflector var meshCenter = Vector3.Transform(mesh.Mesh.Extent.Center, mesh.World * worldMatrix); envMap.SetViewPoint(new Vector3(meshCenter.X, meshCenter.Y, meshCenter.Z)); // Render envmap in single full render pass using // geometry shader instancing. envMap.UpdateSinglePass(context, renderScene); } } #endregion //} #region Render final scene // Reset the vertex, geometry and pixel shader activeVertexShader = vertexShader; activeGeometryShader = null; activePixelShader = blinnPhongShader; // Initialize context (also resetting the render targets) InitializeContext(context, true); // Render the final scene renderScene(context, viewMatrix, projectionMatrix, RenderTargetView, DepthStencilView, null); #endregion // Render FPS fps.Render(); // Render instructions + position changes textRenderer.Render(); // Present the frame Present(); }); #endregion } }
public static async Task<ConsoleExecuteResult> ExecuteAsync(ConsoleCommand command, CommandList commands) { ConsoleExecutingAssembly instance; Dictionary<string, ConsoleExecutingMethod> methodDictionary; if (!ValidateCommand(command, commands, out instance, out methodDictionary)) { return new ConsoleExecuteResult($"Unrecognized command \'{command.LibraryClassName}.{command.Name}\'. " + "Please type a valid command."); } object[] inputArgs; Type typeInfo; string errorMessage; if (BuildCommand(command, instance, methodDictionary, out inputArgs, out typeInfo, out errorMessage)) { // This will throw if the number of arguments provided does not match the number // required by the method signature, even if some are optional: int? id = -1; try { //add the command to the current macro if capture is enabled id = _consoleMacro?.Add(command.RawCommand); var result = await ((Task<ConsoleExecuteResult>) typeInfo.InvokeMember( command.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, instance.Instance, inputArgs)).ConfigureAwait(false); return result; } catch (TargetInvocationException ex) { //remove bad commands from the macro if (id.HasValue && id > -1) { _consoleMacro?.Remove(id.Value); } throw ex.InnerException; } } return new ConsoleExecuteResult(errorMessage); }
public static unsafe int[] GenerateIndexBufferAEN(IndexBufferBinding indexBuffer, VertexBufferBinding vertexBuffer, CommandList commandList = null) { // More info at http://developer.download.nvidia.com/whitepapers/2010/PN-AEN-Triangles-Whitepaper.pdf // This implementation might need some performance improvements var triangleCount = indexBuffer.Count / 3; var newIndices = new int[triangleCount * 12]; var positionMapping = GenerateIndexMapping(vertexBuffer, commandList, "POSITION"); var dominantEdges = new Dictionary <EdgeKeyAEN, EdgeAEN>(); var dominantVertices = new Dictionary <int, int>(); var indexSize = indexBuffer.Is32Bit ? 4 : 2; fixed(byte *indexBufferStart = &indexBuffer.Buffer.GetDataSafe(commandList)[indexBuffer.Offset]) { var triangleIndices = stackalloc int[3]; var positionIndices = stackalloc int[3]; // Step 2: prepare initial data for (int i = 0; i < triangleCount; ++i) { var oldIndices = indexBufferStart + i * 3 * indexSize; if (indexSize == 2) { var oldIndicesShort = (short *)oldIndices; triangleIndices[0] = oldIndicesShort[0]; triangleIndices[1] = oldIndicesShort[1]; triangleIndices[2] = oldIndicesShort[2]; } else { var oldIndicesShort = (int *)oldIndices; triangleIndices[0] = oldIndicesShort[0]; triangleIndices[1] = oldIndicesShort[1]; triangleIndices[2] = oldIndicesShort[2]; } positionIndices[0] = positionMapping.Indices[triangleIndices[0]]; positionIndices[1] = positionMapping.Indices[triangleIndices[1]]; positionIndices[2] = positionMapping.Indices[triangleIndices[2]]; newIndices[i * 12 + 0] = triangleIndices[0]; newIndices[i * 12 + 1] = triangleIndices[1]; newIndices[i * 12 + 2] = triangleIndices[2]; newIndices[i * 12 + 3] = triangleIndices[0]; newIndices[i * 12 + 4] = triangleIndices[1]; newIndices[i * 12 + 5] = triangleIndices[1]; newIndices[i * 12 + 6] = triangleIndices[2]; newIndices[i * 12 + 7] = triangleIndices[2]; newIndices[i * 12 + 8] = triangleIndices[0]; newIndices[i * 12 + 9] = triangleIndices[0]; newIndices[i * 12 + 10] = triangleIndices[1]; newIndices[i * 12 + 11] = triangleIndices[2]; // Step 2b/2c: Build dominant vertex/edge list for (int j = 0; j < 3; ++j) { dominantVertices[positionIndices[j]] = triangleIndices[j]; var edge = new EdgeAEN( triangleIndices[((j + 0) % 3)], triangleIndices[((j + 1) % 3)], positionIndices[((j + 0) % 3)], positionIndices[((j + 1) % 3)]); dominantEdges[new EdgeKeyAEN(edge)] = edge; edge = edge.Reverse(); dominantEdges[new EdgeKeyAEN(edge)] = edge; } } // Step3: Find dominant vertex/edge for (int i = 0; i < triangleCount; ++i) { var oldIndices = indexBufferStart + i * 3 * indexSize; if (indexSize == 2) { var oldIndicesShort = (short *)oldIndices; triangleIndices[0] = oldIndicesShort[0]; triangleIndices[1] = oldIndicesShort[1]; triangleIndices[2] = oldIndicesShort[2]; } else { var oldIndicesShort = (int *)oldIndices; triangleIndices[0] = oldIndicesShort[0]; triangleIndices[1] = oldIndicesShort[1]; triangleIndices[2] = oldIndicesShort[2]; } positionIndices[0] = positionMapping.Indices[triangleIndices[0]]; positionIndices[1] = positionMapping.Indices[triangleIndices[1]]; positionIndices[2] = positionMapping.Indices[triangleIndices[2]]; for (int j = 0; j < 3; ++j) { // Dominant edge int vertexKey; if (dominantVertices.TryGetValue(positionIndices[j], out vertexKey)) { newIndices[i * 12 + 9 + j] = vertexKey; } // Dominant vertex EdgeAEN edge; var edgeKey = new EdgeKeyAEN(positionIndices[((j + 0) % 3)], positionIndices[((j + 1) % 3)]); if (dominantEdges.TryGetValue(edgeKey, out edge)) { newIndices[i * 12 + 3 + j * 2 + 0] = edge.Index0; newIndices[i * 12 + 3 + j * 2 + 1] = edge.Index1; } } } } return(newIndices); }