public static void RSSetScissorRects(this ID3D11DeviceContext context, tagRECT[] rects) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (rects == null) { throw new ArgumentNullException(nameof(rects)); } if (rects.Length == 0) { throw new ArgumentException(null, nameof(rects)); } context.RSSetScissorRects(rects.Length, rects); }
public void Render(ImDrawDataPtr data) { // Avoid rendering when minimized if (data.DisplaySize.X <= 0.0f || data.DisplaySize.Y <= 0.0f) { return; } ID3D11DeviceContext ctx = deviceContext; if (vertexBuffer == null || vertexBufferSize < data.TotalVtxCount) { vertexBuffer?.Release(); vertexBufferSize = data.TotalVtxCount + 5000; BufferDescription desc = new BufferDescription(); desc.Usage = Vortice.Direct3D11.Usage.Dynamic; desc.SizeInBytes = vertexBufferSize * sizeof(ImDrawVert); desc.BindFlags = BindFlags.VertexBuffer; desc.CpuAccessFlags = CpuAccessFlags.Write; vertexBuffer = device.CreateBuffer(desc); } if (indexBuffer == null || indexBufferSize < data.TotalIdxCount) { indexBuffer?.Release(); indexBufferSize = data.TotalIdxCount + 10000; BufferDescription desc = new BufferDescription(); desc.Usage = Vortice.Direct3D11.Usage.Dynamic; desc.SizeInBytes = indexBufferSize * sizeof(ImDrawIdx); desc.BindFlags = BindFlags.IndexBuffer; desc.CpuAccessFlags = CpuAccessFlags.Write; indexBuffer = device.CreateBuffer(desc); } // Upload vertex/index data into a single contiguous GPU buffer var vertexResource = ctx.Map(vertexBuffer, 0, MapMode.WriteDiscard, Vortice.Direct3D11.MapFlags.None); var indexResource = ctx.Map(indexBuffer, 0, MapMode.WriteDiscard, Vortice.Direct3D11.MapFlags.None); var vertexResourcePointer = (ImDrawVert *)vertexResource.DataPointer; var indexResourcePointer = (ImDrawIdx *)indexResource.DataPointer; for (int n = 0; n < data.CmdListsCount; n++) { var cmdlList = data.CmdListsRange[n]; var vertBytes = cmdlList.VtxBuffer.Size * sizeof(ImDrawVert); Buffer.MemoryCopy((void *)cmdlList.VtxBuffer.Data, vertexResourcePointer, vertBytes, vertBytes); var idxBytes = cmdlList.IdxBuffer.Size * sizeof(ImDrawIdx); Buffer.MemoryCopy((void *)cmdlList.IdxBuffer.Data, indexResourcePointer, idxBytes, idxBytes); vertexResourcePointer += cmdlList.VtxBuffer.Size; indexResourcePointer += cmdlList.IdxBuffer.Size; } ctx.Unmap(vertexBuffer, 0); ctx.Unmap(indexBuffer, 0); // Setup orthographic projection matrix into our constant buffer // Our visible imgui space lies from draw_data.DisplayPos (top left) to draw_data.DisplayPos+data_data.DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. var constResource = ctx.Map(constantBuffer, 0, MapMode.WriteDiscard, Vortice.Direct3D11.MapFlags.None); var span = constResource.AsSpan <float>(VertexConstantBufferSize); float L = data.DisplayPos.X; float R = data.DisplayPos.X + data.DisplaySize.X; float T = data.DisplayPos.Y; float B = data.DisplayPos.Y + data.DisplaySize.Y; float[] mvp = { 2.0f / (R - L), 0.0f, 0.0f, 0.0f, 0.0f, 2.0f / (T - B), 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f, }; mvp.CopyTo(span); ctx.Unmap(constantBuffer, 0); SetupRenderState(data, ctx); // Render command lists // (Because we merged all buffers into a single one, we maintain our own offset into them) int global_idx_offset = 0; int global_vtx_offset = 0; Vector2 clip_off = data.DisplayPos; for (int n = 0; n < data.CmdListsCount; n++) { var cmdList = data.CmdListsRange[n]; for (int i = 0; i < cmdList.CmdBuffer.Size; i++) { var cmd = cmdList.CmdBuffer[i]; if (cmd.UserCallback != IntPtr.Zero) { throw new NotImplementedException("user callbacks not implemented"); } else { var rect = new Rect((int)(cmd.ClipRect.X - clip_off.X), (int)(cmd.ClipRect.Y - clip_off.Y), (int)(cmd.ClipRect.Z - clip_off.X), (int)(cmd.ClipRect.W - clip_off.Y)); ctx.RSSetScissorRects(rect); textureResources.TryGetValue(cmd.TextureId, out var texture); if (texture != null) { ctx.PSSetShaderResources(0, texture); } ctx.DrawIndexed((int)cmd.ElemCount, (int)(cmd.IdxOffset + global_idx_offset), (int)(cmd.VtxOffset + global_vtx_offset)); } } global_idx_offset += cmdList.IdxBuffer.Size; global_vtx_offset += cmdList.VtxBuffer.Size; } }