unsafe public CommandList BuildCommandList(GraphicsDevice graphicsDevice, Framebuffer framebuffer) { ResourceFactory factory = graphicsDevice.ResourceFactory; Shader _vsShader = null; Shader _psShader = null; DeviceBuffer _vertexBuffer = null; Pipeline _pipeline = null; Veldrid.CommandList _commandList = null; try { #region --- try #region --- shaders { string _vsname = null; string _psname = null; switch (graphicsDevice.BackendType) { case GraphicsBackend.Direct3D11: _vsname = "Test_Colored2DVertices.vs"; _psname = "Test_Colored2DVertices.ps"; break; case GraphicsBackend.Metal: _vsname = "Test_Colored2DVertices_vs.msl"; _psname = "Test_Colored2DVertices_ps.msl"; break; case GraphicsBackend.Vulkan: _vsname = "Test_Colored2DVertices_vs.spv"; _psname = "Test_Colored2DVertices_ps.spv"; break; case GraphicsBackend.OpenGL: _vsname = "Test_Colored2DVertices_vs.glsl"; _psname = "Test_Colored2DVertices_ps.glsl"; break; case GraphicsBackend.OpenGLES: _vsname = "Test_Colored2DVertices_vs_es.glsl"; _psname = "Test_Colored2DVertices_ps_es.glsl"; break; } string _vs = loadResourceString(Assembly.GetExecutingAssembly(), _vsname); if (string.IsNullOrEmpty(_vs)) { return(null); } string _ps = loadResourceString(Assembly.GetExecutingAssembly(), _psname); if (string.IsNullOrEmpty(_ps)) { return(null); } ShaderDescription vertexShaderDesc = new ShaderDescription( ShaderStages.Vertex, Encoding.UTF8.GetBytes(_vs), "_VertexShader"); ShaderDescription fragmentShaderDesc = new ShaderDescription( ShaderStages.Fragment, Encoding.UTF8.GetBytes(_ps), "_PixelShader"); _vsShader = factory.CreateShader(vertexShaderDesc); _psShader = factory.CreateShader(fragmentShaderDesc); } #endregion VertexLayoutDescription _vertexLayout = new VertexLayoutDescription(); int _vertexCount; #region --- _vertexBuffer + _vertexLayout { int _count = 10; byte[] _data = Build_2DColoredQuads_16SNorm_8UNorm(_count, _count, out _vertexCount); // Veldrid.BufferDescription vbDescription = new Veldrid.BufferDescription( (uint)_data.Length, BufferUsage.VertexBuffer); _vertexBuffer = factory.CreateBuffer(vbDescription); fixed(byte *_pdata = _data) { graphicsDevice.UpdateBuffer(_vertexBuffer, bufferOffsetInBytes: 0, (IntPtr)_pdata, (uint)_data.Length); } _vertexLayout = new VertexLayoutDescription( new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Short2_Norm, offset: 0), new VertexElementDescription("Color", VertexElementSemantic.Color, VertexElementFormat.Byte4_Norm, offset: 2 * sizeof(short))); } #endregion #region --- pipeline { GraphicsPipelineDescription _pipelineDescription = new GraphicsPipelineDescription(); _pipelineDescription.BlendState = Veldrid.BlendStateDescription.SingleOverrideBlend; _pipelineDescription.DepthStencilState = new Veldrid.DepthStencilStateDescription( depthTestEnabled: false, depthWriteEnabled: false, comparisonKind: ComparisonKind.LessEqual); _pipelineDescription.RasterizerState = new Veldrid.RasterizerStateDescription( cullMode: FaceCullMode.None, fillMode: PolygonFillMode.Solid, frontFace: FrontFace.Clockwise, depthClipEnabled: true, // Android ? scissorTestEnabled: false); _pipelineDescription.PrimitiveTopology = Veldrid.PrimitiveTopology.TriangleList; _pipelineDescription.ResourceLayouts = System.Array.Empty <ResourceLayout>(); _pipelineDescription.ShaderSet = new ShaderSetDescription( vertexLayouts: new VertexLayoutDescription[] { _vertexLayout }, shaders: new Shader[] { _vsShader, _psShader }); _pipelineDescription.Outputs = framebuffer.OutputDescription; // _offscreenFB.OutputDescription; _pipeline = factory.CreateGraphicsPipeline(_pipelineDescription); } #endregion #region --- commandList { _commandList = factory.CreateCommandList(); // Begin() must be called before commands can be issued. _commandList.Begin(); _commandList.SetPipeline(_pipeline); // We want to render directly to the output window. _commandList.SetFramebuffer(framebuffer); _commandList.SetFullViewports(); _commandList.ClearColorTarget(0, RgbaFloat.DarkRed); // Set all relevant state to draw our quad. _commandList.SetVertexBuffer(0, _vertexBuffer); _commandList.Draw(vertexCount: (uint)_vertexCount); // End() must be called before commands can be submitted for execution. _commandList.End(); } #endregion CommandList vret = _commandList; _commandList = null; return(vret); #endregion } catch (Exception e) { return(null); } finally { _vsShader?.Dispose(); _psShader?.Dispose(); _vertexBuffer?.Dispose(); _pipeline?.Dispose(); _commandList?.Dispose(); } }
private unsafe void RenderImDrawData(DrawData *draw_data, GraphicsDevice gd, CommandList cl) { uint vertexOffsetInVertices = 0; uint indexOffsetInElements = 0; if (draw_data->CmdListsCount == 0) { return; } uint totalVBSize = (uint)(draw_data->TotalVtxCount * sizeof(DrawVert)); if (totalVBSize > _vertexBuffer.SizeInBytes) { _vertexBuffer.Dispose(); _vertexBuffer = gd.ResourceFactory.CreateVertexBuffer(new BufferDescription((ulong)(totalVBSize * 1.5f), true)); } uint totalIBSize = (uint)(draw_data->TotalIdxCount * sizeof(ushort)); if (totalIBSize > _indexBuffer.SizeInBytes) { _indexBuffer.Dispose(); _indexBuffer = gd.ResourceFactory.CreateIndexBuffer(new IndexBufferDescription((ulong)(totalIBSize * 1.5f), IndexFormat.UInt16, true)); } for (int i = 0; i < draw_data->CmdListsCount; i++) { NativeDrawList *cmd_list = draw_data->CmdLists[i]; cl.UpdateBuffer( _vertexBuffer, (uint)(vertexOffsetInVertices * sizeof(DrawVert)), new IntPtr(cmd_list->VtxBuffer.Data), (uint)(cmd_list->VtxBuffer.Size * sizeof(DrawVert))); cl.UpdateBuffer( _indexBuffer, (uint)(indexOffsetInElements * sizeof(ushort)), new IntPtr(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 { var io = ImGui.GetIO(); Matrix4x4 mvp = Matrix4x4.CreateOrthographicOffCenter( 0f, io.DisplaySize.X, io.DisplaySize.Y, 0.0f, -1.0f, 1.0f); cl.UpdateBuffer(_projMatrixBuffer, 0, ref mvp); } cl.SetVertexBuffer(0, _vertexBuffer); cl.SetIndexBuffer(_indexBuffer); cl.SetPipeline(_pipeline); cl.SetResourceSet(0, _resourceSet); ImGui.ScaleClipRects(draw_data, ImGui.GetIO().DisplayFramebufferScale); // Render command lists int vtx_offset = 0; int idx_offset = 0; for (int n = 0; n < draw_data->CmdListsCount; n++) { NativeDrawList *cmd_list = draw_data->CmdLists[n]; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { DrawCmd *pcmd = &(((DrawCmd *)cmd_list->CmdBuffer.Data)[cmd_i]); if (pcmd->UserCallback != IntPtr.Zero) { throw new NotImplementedException(); } else { if (pcmd->TextureId != IntPtr.Zero) { if (pcmd->TextureId != new IntPtr(_fontAtlasID)) { throw new NotImplementedException(); } } cl.SetScissorRect( 0, (uint)pcmd->ClipRect.X, (uint)pcmd->ClipRect.Y, (uint)pcmd->ClipRect.Z, (uint)pcmd->ClipRect.W); cl.Draw(pcmd->ElemCount, 1, (uint)idx_offset, vtx_offset, 0); } idx_offset += (int)pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.Size; } }