Flutter Impeller
imgui_impl_impeller.h File Reference
#include <memory>
#include "third_party/imgui/imgui.h"

Go to the source code of this file.

Namespaces

 impeller
 

Functions

IMGUI_IMPL_API bool ImGui_ImplImpeller_Init (const std::shared_ptr< impeller::Context > &context)
 
IMGUI_IMPL_API void ImGui_ImplImpeller_Shutdown ()
 
IMGUI_IMPL_API void ImGui_ImplImpeller_RenderDrawData (ImDrawData *draw_data, impeller::RenderPass &renderpass)
 

Function Documentation

◆ ImGui_ImplImpeller_Init()

IMGUI_IMPL_API bool ImGui_ImplImpeller_Init ( const std::shared_ptr< impeller::Context > &  context)

Definition at line 51 of file imgui_impl_impeller.cc.

52  {
53  ImGuiIO& io = ImGui::GetIO();
54  IM_ASSERT(io.BackendRendererUserData == nullptr &&
55  "Already initialized a renderer backend!");
56 
57  // Setup backend capabilities flags
58  auto* bd = new ImGui_ImplImpeller_Data();
59  io.BackendRendererUserData = reinterpret_cast<void*>(bd);
60  io.BackendRendererName = "imgui_impl_impeller";
61  io.BackendFlags |=
62  ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the
63  // ImDrawCmd::VtxOffset field,
64  // allowing for large meshes.
65 
66  bd->context = context;
67 
68  // Generate/upload the font atlas.
69  {
70  unsigned char* pixels;
71  int width, height;
72  io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
73 
74  auto texture_descriptor = impeller::TextureDescriptor{};
76  texture_descriptor.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
77  texture_descriptor.size = {width, height};
78  texture_descriptor.mip_count = 1u;
79 
80  bd->font_texture =
81  context->GetResourceAllocator()->CreateTexture(texture_descriptor);
82  IM_ASSERT(bd->font_texture != nullptr &&
83  "Could not allocate ImGui font texture.");
84  bd->font_texture->SetLabel("ImGui Font Texture");
85 
86  [[maybe_unused]] bool uploaded = bd->font_texture->SetContents(
87  pixels, texture_descriptor.GetByteSizeOfBaseMipLevel());
88  IM_ASSERT(uploaded &&
89  "Could not upload ImGui font texture to device memory.");
90  }
91 
92  // Build the raster pipeline.
93  {
94  auto desc = impeller::PipelineBuilder<impeller::ImguiRasterVertexShader,
95  impeller::ImguiRasterFragmentShader>::
96  MakeDefaultPipelineDescriptor(*context);
97  IM_ASSERT(desc.has_value() && "Could not create Impeller pipeline");
98  if (desc.has_value()) { // Needed to silence clang-tidy check
99  // bugprone-unchecked-optional-access.
100  desc->ClearStencilAttachments();
101  desc->ClearDepthAttachment();
102  }
103 
104  bd->pipeline =
105  context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
106  IM_ASSERT(bd->pipeline != nullptr && "Could not create ImGui pipeline.");
107 
108  bd->sampler = context->GetSamplerLibrary()->GetSampler({});
109  IM_ASSERT(bd->pipeline != nullptr && "Could not create ImGui sampler.");
110  }
111 
112  return true;
113 }

References impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, and impeller::TextureDescriptor::storage_mode.

Referenced by impeller::Playground::OpenPlaygroundHere().

◆ ImGui_ImplImpeller_RenderDrawData()

IMGUI_IMPL_API void ImGui_ImplImpeller_RenderDrawData ( ImDrawData *  draw_data,
impeller::RenderPass renderpass 
)

Definition at line 122 of file imgui_impl_impeller.cc.

123  {
124  if (draw_data->CmdListsCount == 0) {
125  return; // Nothing to render.
126  }
127 
128  using VS = impeller::ImguiRasterVertexShader;
129  using FS = impeller::ImguiRasterFragmentShader;
130 
132  IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplImpeller_Init()?");
133 
134  size_t total_vtx_bytes = draw_data->TotalVtxCount * sizeof(VS::PerVertexData);
135  size_t total_idx_bytes = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
136  if (!total_vtx_bytes || !total_idx_bytes) {
137  return; // Nothing to render.
138  }
139 
140  // Allocate buffer for vertices + indices.
142  buffer_desc.size = total_vtx_bytes + total_idx_bytes;
144 
145  auto buffer = bd->context->GetResourceAllocator()->CreateBuffer(buffer_desc);
146  buffer->SetLabel(impeller::SPrintF("ImGui vertex+index buffer"));
147 
148  auto display_rect =
149  impeller::Rect(draw_data->DisplayPos.x, draw_data->DisplayPos.y,
150  draw_data->DisplaySize.x, draw_data->DisplaySize.y);
151 
152  auto viewport = impeller::Viewport{
153  .rect = impeller::Rect(
154  display_rect.origin.x * draw_data->FramebufferScale.x,
155  display_rect.origin.y * draw_data->FramebufferScale.y,
156  display_rect.size.width * draw_data->FramebufferScale.x,
157  display_rect.size.height * draw_data->FramebufferScale.y)};
158 
159  // Allocate vertex shader uniform buffer.
160  VS::UniformBuffer uniforms;
161  uniforms.mvp = impeller::Matrix::MakeOrthographic(display_rect.size)
162  .Translate(-display_rect.origin);
163  auto vtx_uniforms =
164  render_pass.GetTransientsBuffer().EmplaceUniform(uniforms);
165 
166  size_t vertex_buffer_offset = 0;
167  size_t index_buffer_offset = total_vtx_bytes;
168 
169  for (int draw_list_i = 0; draw_list_i < draw_data->CmdListsCount;
170  draw_list_i++) {
171  const ImDrawList* cmd_list = draw_data->CmdLists[draw_list_i];
172 
173  // Convert ImGui's per-vertex data (`ImDrawVert`) into the per-vertex data
174  // required by the shader (`VS::PerVectexData`). The only difference is that
175  // `ImDrawVert` uses an `int` for the color and the impeller shader uses 4
176  // floats.
177 
178  // TODO(102778): Remove the need for this by adding support for attribute
179  // mapping of uint32s host-side to vec4s shader-side in
180  // impellerc.
181  std::vector<VS::PerVertexData> vtx_data;
182  vtx_data.reserve(cmd_list->VtxBuffer.size());
183  for (const auto& v : cmd_list->VtxBuffer) {
184  ImVec4 color = ImGui::ColorConvertU32ToFloat4(v.col);
185  vtx_data.push_back({{v.pos.x, v.pos.y}, //
186  {v.uv.x, v.uv.y}, //
187  {color.x, color.y, color.z, color.w}});
188  }
189 
190  auto draw_list_vtx_bytes =
191  static_cast<size_t>(vtx_data.size() * sizeof(VS::PerVertexData));
192  auto draw_list_idx_bytes =
193  static_cast<size_t>(cmd_list->IdxBuffer.size_in_bytes());
194  if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vtx_data.data()),
195  impeller::Range{0, draw_list_vtx_bytes},
196  vertex_buffer_offset)) {
197  IM_ASSERT(false && "Could not copy vertices to buffer.");
198  }
199  if (!buffer->CopyHostBuffer(
200  reinterpret_cast<uint8_t*>(cmd_list->IdxBuffer.Data),
201  impeller::Range{0, draw_list_idx_bytes}, index_buffer_offset)) {
202  IM_ASSERT(false && "Could not copy indices to buffer.");
203  }
204 
205  for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
206  const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
207 
208  if (pcmd->UserCallback) {
209  pcmd->UserCallback(cmd_list, pcmd);
210  } else {
211  // Make the clip rect relative to the viewport.
212  auto clip_rect = impeller::Rect::MakeLTRB(
213  (pcmd->ClipRect.x - draw_data->DisplayPos.x) *
214  draw_data->FramebufferScale.x,
215  (pcmd->ClipRect.y - draw_data->DisplayPos.y) *
216  draw_data->FramebufferScale.y,
217  (pcmd->ClipRect.z - draw_data->DisplayPos.x) *
218  draw_data->FramebufferScale.x,
219  (pcmd->ClipRect.w - draw_data->DisplayPos.y) *
220  draw_data->FramebufferScale.y);
221  {
222  // Clamp the clip to the viewport bounds.
223  auto visible_clip = clip_rect.Intersection(viewport.rect);
224  if (!visible_clip.has_value()) {
225  continue; // Nothing to render.
226  }
227  clip_rect = visible_clip.value();
228  }
229  {
230  // Clamp the clip to ensure it never goes outside of the render
231  // target.
232  auto visible_clip = clip_rect.Intersection(
233  impeller::Rect::MakeSize(render_pass.GetRenderTargetSize()));
234  if (!visible_clip.has_value()) {
235  continue; // Nothing to render.
236  }
237  clip_rect = visible_clip.value();
238  }
239 
240  impeller::Command cmd;
241  DEBUG_COMMAND_INFO(cmd,
242  impeller::SPrintF("ImGui draw list %d (command %d)",
243  draw_list_i, cmd_i));
244 
245  cmd.viewport = viewport;
246  cmd.scissor = impeller::IRect(clip_rect);
247 
248  cmd.pipeline = bd->pipeline;
249  VS::BindUniformBuffer(cmd, vtx_uniforms);
250  FS::BindTex(cmd, bd->font_texture, bd->sampler);
251 
252  size_t vb_start =
253  vertex_buffer_offset + pcmd->VtxOffset * sizeof(ImDrawVert);
254 
255  impeller::VertexBuffer vertex_buffer;
256  vertex_buffer.vertex_buffer = {
257  .buffer = buffer,
258  .range = impeller::Range(vb_start, draw_list_vtx_bytes - vb_start)};
259  vertex_buffer.index_buffer = {
260  .buffer = buffer,
261  .range = impeller::Range(
262  index_buffer_offset + pcmd->IdxOffset * sizeof(ImDrawIdx),
263  pcmd->ElemCount * sizeof(ImDrawIdx))};
264  vertex_buffer.vertex_count = pcmd->ElemCount;
265  vertex_buffer.index_type = impeller::IndexType::k16bit;
266  cmd.BindVertices(vertex_buffer);
267  cmd.base_vertex = pcmd->VtxOffset;
268 
269  render_pass.AddCommand(std::move(cmd));
270  }
271  }
272 
273  vertex_buffer_offset += draw_list_vtx_bytes;
274  index_buffer_offset += draw_list_idx_bytes;
275  }
276 }

References impeller::RenderPass::AddCommand(), impeller::Command::base_vertex, impeller::Command::BindVertices(), impeller::BufferView::buffer, DEBUG_COMMAND_INFO, impeller::HostBuffer::EmplaceUniform(), impeller::RenderPass::GetRenderTargetSize(), impeller::RenderPass::GetTransientsBuffer(), ImGui_ImplImpeller_GetBackendData(), impeller::VertexBuffer::index_buffer, impeller::VertexBuffer::index_type, impeller::k16bit, impeller::kHostVisible, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeOrthographic(), impeller::TRect< Scalar >::MakeSize(), impeller::Command::pipeline, impeller::Viewport::rect, impeller::Command::scissor, impeller::DeviceBufferDescriptor::size, impeller::SPrintF(), impeller::DeviceBufferDescriptor::storage_mode, impeller::Matrix::Translate(), impeller::VertexBuffer::vertex_buffer, impeller::VertexBuffer::vertex_count, and impeller::Command::viewport.

Referenced by impeller::Playground::OpenPlaygroundHere().

◆ ImGui_ImplImpeller_Shutdown()

IMGUI_IMPL_API void ImGui_ImplImpeller_Shutdown ( )

Definition at line 115 of file imgui_impl_impeller.cc.

115  {
117  IM_ASSERT(bd != nullptr &&
118  "No renderer backend to shutdown, or already shutdown?");
119  delete bd;
120 }

References ImGui_ImplImpeller_GetBackendData().

Referenced by impeller::Playground::OpenPlaygroundHere().

impeller::Command
An object used to specify work to the GPU along with references to resources the GPU will used when d...
Definition: command.h:99
impeller::VertexBuffer::index_type
IndexType index_type
Definition: vertex_buffer.h:18
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:31
impeller::Command::scissor
std::optional< IRect > scissor
Definition: command.h:169
impeller::IndexType::k16bit
@ k16bit
impeller::Viewport::rect
Rect rect
Definition: formats.h:353
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:13
impeller::VertexBuffer
Definition: vertex_buffer.h:12
impeller::Command::viewport
std::optional< Viewport > viewport
Definition: command.h:163
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:15
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
ImGui_ImplImpeller_GetBackendData
static ImGui_ImplImpeller_Data * ImGui_ImplImpeller_GetBackendData()
Definition: imgui_impl_impeller.cc:44
impeller::VertexBuffer::vertex_buffer
BufferView vertex_buffer
Definition: vertex_buffer.h:13
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::VertexBuffer::vertex_count
size_t vertex_count
Definition: vertex_buffer.h:17
impeller::Command::base_vertex
uint64_t base_vertex
Definition: command.h:156
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::BufferView::buffer
std::shared_ptr< const Buffer > buffer
Definition: buffer_view.h:14
impeller::DeviceBufferDescriptor::storage_mode
StorageMode storage_mode
Definition: device_buffer_descriptor.h:14
impeller::Matrix::Translate
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:233
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:306
impeller::IRect
TRect< int64_t > IRect
Definition: rect.h:307
impeller::Viewport
Definition: formats.h:352
impeller::VertexBuffer::index_buffer
BufferView index_buffer
Definition: vertex_buffer.h:14
impeller::Range
Definition: range.h:13
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:52
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:448
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:40
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:40
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:39
impeller::Command::BindVertices
bool BindVertices(const VertexBuffer &buffer)
Specify the vertex and index buffer to use for this command.
Definition: command.cc:15
impeller::Command::pipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > pipeline
Definition: command.h:103
impeller::PipelineBuilder
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
Definition: pipeline_builder.h:31
ImGui_ImplImpeller_Data
Definition: imgui_impl_impeller.cc:37