| Flutter Impeller |

Namespaces | Functions
imgui_impl_impeller.h File Reference
`#include <memory>`
`#include "impeller/core/host_buffer.h"`
`#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, impeller::HostBuffer &host_buffer)

## Function Documentation

## ◆ ImGui_ImplImpeller_Init()

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

Definition at line 57 of file imgui_impl_impeller.cc.

58 {
59 ImGuiIO& io = ImGui::GetIO();
60 IM_ASSERT(io.BackendRendererUserData == nullptr &&
61 "Already initialized a renderer backend!");
62
63 // Setup backend capabilities flags
64 auto* bd =
65 new ImGui_ImplImpeller_Data(context->GetSamplerLibrary()->GetSampler({}));
66 io.BackendRendererUserData = reinterpret_cast<void*>(bd);
67 io.BackendRendererName = "imgui_impl_impeller";
68 io.BackendFlags |=
69 ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the
70 // ImDrawCmd::VtxOffset field,
71 // allowing for large meshes.
72
73 bd->context = context;
74
75 // Generate/upload the font atlas.
76 {
77 unsigned char* pixels;
78 int width, height;
79 io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
80
81 impeller::TextureDescriptor texture_descriptor;
82 texture_descriptor.storage_mode = impeller::StorageMode::kDevicePrivate;
83 texture_descriptor.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
84 texture_descriptor.size = {width, height};
85 texture_descriptor.mip_count = 1u;
86
87 bd->font_texture =
88 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
89 IM_ASSERT(bd->font_texture != nullptr &&
90 "Could not allocate ImGui font texture.");
91 bd->font_texture->SetLabel("ImGui Font Texture");
92
93 auto command_buffer = context->CreateCommandBuffer();
94 auto blit_pass = command_buffer->CreateBlitPass();
95 auto mapping = std::make_shared<fml::NonOwnedMapping>(
96 reinterpret_cast<const uint8_t*>(pixels),
97 texture_descriptor.GetByteSizeOfBaseMipLevel());
98 auto device_buffer =
99 context->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
100
101 blit_pass->AddCopy(impeller::DeviceBuffer::AsBufferView(device_buffer),
102 bd->font_texture);
103 blit_pass->EncodeCommands();
104
105 [[maybe_unused]] bool uploaded =
106 context->GetCommandQueue()->Submit({command_buffer}).ok();
107 IM_ASSERT(uploaded &&
108 "Could not upload ImGui font texture to device memory.");
109 }
110
111 // Build the raster pipeline.
112 {
113 auto desc = impeller::PipelineBuilder<impeller::ImguiRasterVertexShader,
114 impeller::ImguiRasterFragmentShader>::
115 MakeDefaultPipelineDescriptor(*context);
116 IM_ASSERT(desc.has_value() && "Could not create Impeller pipeline");
117 if (desc.has_value()) { // Needed to silence clang-tidy check
118 // bugprone-unchecked-optional-access.
119 desc->ClearStencilAttachments();
120 desc->ClearDepthAttachment();
121 }
122
123 bd->pipeline =
124 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
125 IM_ASSERT(bd->pipeline != nullptr && "Could not create ImGui pipeline.");
126 IM_ASSERT(bd->pipeline != nullptr && "Could not create ImGui sampler.");
127 }
128
129 return true;
130 }
impeller::DeviceBuffer::AsBufferView
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
Definition: device_buffer.cc:18
impeller::StorageMode::kDevicePrivate
@ kDevicePrivate
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
ImGui_ImplImpeller_Data
Definition: imgui_impl_impeller.cc:39
impeller::PipelineBuilder
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
Definition: pipeline_builder.h:31
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:38
impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel
constexpr size_t GetByteSizeOfBaseMipLevel() const
Definition: texture_descriptor.h:48
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:42
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:39
impeller::TextureDescriptor::mip_count
size_t mip_count
Definition: texture_descriptor.h:43
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:41

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel(), impeller::kDevicePrivate, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::mip_count, impeller::TextureDescriptor::size, 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,
|  | impeller::HostBuffer & | host_buffer
| ) |  |

Definition at line 139 of file imgui_impl_impeller.cc.

141 {
142 if (draw_data->CmdListsCount == 0) {
143 return; // Nothing to render.
144 }
145
146 using VS = impeller::ImguiRasterVertexShader;
147 using FS = impeller::ImguiRasterFragmentShader;
148
149 auto* bd = ImGui_ImplImpeller_GetBackendData();
150 IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplImpeller_Init()?");
151
152 size_t total_vtx_bytes = draw_data->TotalVtxCount * sizeof(VS::PerVertexData);
153 size_t total_idx_bytes = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
154 if (!total_vtx_bytes || !total_idx_bytes) {
155 return; // Nothing to render.
156 }
157
158 // Allocate buffer for vertices + indices.
159 impeller::DeviceBufferDescriptor buffer_desc;
160 buffer_desc.size = total_vtx_bytes + total_idx_bytes;
161 buffer_desc.storage_mode = impeller::StorageMode::kHostVisible;
162
163 auto buffer = bd->context->GetResourceAllocator()->CreateBuffer(buffer_desc);
164 buffer->SetLabel("ImGui vertex+index buffer");
165
166 auto display_rect = impeller::Rect::MakeXYWH(
167 draw_data->DisplayPos.x, draw_data->DisplayPos.y,
168 draw_data->DisplaySize.x, draw_data->DisplaySize.y);
169
170 auto viewport = impeller::Viewport{
171 .rect = display_rect.Scale(draw_data->FramebufferScale.x,
172 draw_data->FramebufferScale.y)};
173
174 // Allocate vertex shader uniform buffer.
175 VS::UniformBuffer uniforms;
176 uniforms.mvp = impeller::Matrix::MakeOrthographic(display_rect.GetSize())
177 .Translate(-display_rect.GetOrigin());
178 auto vtx_uniforms = host_buffer.EmplaceUniform(uniforms);
179
180 size_t vertex_buffer_offset = 0;
181 size_t index_buffer_offset = total_vtx_bytes;
182
183 for (int draw_list_i = 0; draw_list_i < draw_data->CmdListsCount;
184 draw_list_i++) {
185 const ImDrawList* cmd_list = draw_data->CmdLists[draw_list_i];
186
187 // Convert ImGui's per-vertex data (`ImDrawVert`) into the per-vertex data
188 // required by the shader (`VS::PerVectexData`). The only difference is that
189 // `ImDrawVert` uses an `int` for the color and the impeller shader uses 4
190 // floats.
191
192 // TODO(102778): Remove the need for this by adding support for attribute
193 // mapping of uint32s host-side to vec4s shader-side in
194 // impellerc.
195 std::vector<VS::PerVertexData> vtx_data;
196 vtx_data.reserve(cmd_list->VtxBuffer.size());
197 for (const auto& v : cmd_list->VtxBuffer) {
198 ImVec4 color = ImGui::ColorConvertU32ToFloat4(v.col);
199 vtx_data.push_back({{v.pos.x, v.pos.y}, //
200 {v.uv.x, v.uv.y}, //
201 {color.x, color.y, color.z, color.w}});
202 }
203
204 auto draw_list_vtx_bytes =
205 static_cast<size_t>(vtx_data.size() * sizeof(VS::PerVertexData));
206 auto draw_list_idx_bytes =
207 static_cast<size_t>(cmd_list->IdxBuffer.size_in_bytes());
208 if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vtx_data.data()),
209 impeller::Range{0, draw_list_vtx_bytes},
210 vertex_buffer_offset)) {
211 IM_ASSERT(false && "Could not copy vertices to buffer.");
212 }
213 if (!buffer->CopyHostBuffer(
214 reinterpret_cast<uint8_t*>(cmd_list->IdxBuffer.Data),
215 impeller::Range{0, draw_list_idx_bytes}, index_buffer_offset)) {
216 IM_ASSERT(false && "Could not copy indices to buffer.");
217 }
218
219 for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
220 const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
221
222 if (pcmd->UserCallback) {
223 pcmd->UserCallback(cmd_list, pcmd);
224 } else {
225 // Make the clip rect relative to the viewport.
226 auto clip_rect = impeller::Rect::MakeLTRB(
227 (pcmd->ClipRect.x - draw_data->DisplayPos.x) *
228 draw_data->FramebufferScale.x,
229 (pcmd->ClipRect.y - draw_data->DisplayPos.y) *
230 draw_data->FramebufferScale.y,
231 (pcmd->ClipRect.z - draw_data->DisplayPos.x) *
232 draw_data->FramebufferScale.x,
233 (pcmd->ClipRect.w - draw_data->DisplayPos.y) *
234 draw_data->FramebufferScale.y);
235 {
236 // Clamp the clip to the viewport bounds.
237 auto visible_clip = clip_rect.Intersection(viewport.rect);
238 if (!visible_clip.has_value()) {
239 continue; // Nothing to render.
240 }
241 clip_rect = visible_clip.value();
242 }
243 {
244 // Clamp the clip to ensure it never goes outside of the render
245 // target.
246 auto visible_clip = clip_rect.Intersection(
247 impeller::Rect::MakeSize(render_pass.GetRenderTargetSize()));
248 if (!visible_clip.has_value()) {
249 continue; // Nothing to render.
250 }
251 clip_rect = visible_clip.value();
252 }
253
254 render_pass.SetCommandLabel(
255 std::format("ImGui draw list {} (command {})", draw_list_i, cmd_i));
256 render_pass.SetViewport(viewport);
257 render_pass.SetScissor(impeller::IRect32::RoundOut(clip_rect));
258 render_pass.SetPipeline(bd->pipeline);
259 VS::BindUniformBuffer(render_pass, vtx_uniforms);
260 FS::BindTex(render_pass, bd->font_texture, bd->sampler);
261
262 size_t vb_start =
263 vertex_buffer_offset + pcmd->VtxOffset * sizeof(ImDrawVert);
264
265 impeller::VertexBuffer vertex_buffer;
266 vertex_buffer.vertex_buffer = impeller::BufferView(
267 buffer, impeller::Range(vb_start, draw_list_vtx_bytes - vb_start));
268 vertex_buffer.index_buffer = impeller::BufferView(
269 buffer, impeller::Range(index_buffer_offset +
270 pcmd->IdxOffset * sizeof(ImDrawIdx),
271 pcmd->ElemCount * sizeof(ImDrawIdx)));
272 vertex_buffer.vertex_count = pcmd->ElemCount;
273 vertex_buffer.index_type = impeller::IndexType::k16bit;
274 render_pass.SetVertexBuffer(std::move(vertex_buffer));
275 render_pass.SetBaseVertex(pcmd->VtxOffset);
276
277 render_pass.Draw().ok();
278 }
279 }
280
281 vertex_buffer_offset += draw_list_vtx_bytes;
282 index_buffer_offset += draw_list_idx_bytes;
283 }
284 host_buffer.Reset();
285 }
impeller::HostBuffer::EmplaceUniform
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
Definition: host_buffer.h:47
impeller::HostBuffer::Reset
void Reset()
Resets the contents of the HostBuffer to nothing so it can be reused.
Definition: host_buffer.cc:229
ImGui_ImplImpeller_GetBackendData
static ImGui_ImplImpeller_Data * ImGui_ImplImpeller_GetBackendData()
Definition: imgui_impl_impeller.cc:50
impeller::IndexType::k16bit
@ k16bit
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::FS
LinePipeline::FragmentShader FS
Definition: line_contents.cc:14
impeller::VS
LinePipeline::VertexShader VS
Definition: line_contents.cc:13
impeller::BufferView
Definition: buffer_view.h:19
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:14
impeller::DeviceBufferDescriptor::storage_mode
StorageMode storage_mode
Definition: device_buffer_descriptor.h:15
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:16
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:633
impeller::Matrix::Translate
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:263
impeller::Range
Definition: range.h:13
impeller::TRect::RoundOut
RoundOut(const TRect< U > &r)
Definition: rect.h:679
impeller::TRect::Scale
constexpr TRect Scale(Type scale) const
Definition: rect.h:202
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::VertexBuffer
Definition: vertex_buffer.h:15
impeller::VertexBuffer::index_type
IndexType index_type
Definition: vertex_buffer.h:31
impeller::VertexBuffer::vertex_count
size_t vertex_count
Definition: vertex_buffer.h:25
impeller::VertexBuffer::index_buffer
BufferView index_buffer
The index buffer binding used by the vertex shader stage.
Definition: vertex_buffer.h:20
impeller::VertexBuffer::vertex_buffer
BufferView vertex_buffer
Definition: vertex_buffer.h:16
impeller::Viewport
Definition: formats.h:406
impeller::Viewport::rect
Rect rect
Definition: formats.h:407

References impeller::RenderPass::Draw(), impeller::HostBuffer::EmplaceUniform(), impeller::RenderPass::GetRenderTargetSize(), 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::TRect< Scalar >::MakeXYWH(), impeller::Viewport::rect, impeller::HostBuffer::Reset(), impeller::TRect< T >::RoundOut(), impeller::TRect< T >::Scale(), impeller::RenderPass::SetBaseVertex(), impeller::RenderPass::SetCommandLabel(), impeller::RenderPass::SetPipeline(), impeller::RenderPass::SetScissor(), impeller::RenderPass::SetVertexBuffer(), impeller::RenderPass::SetViewport(), impeller::DeviceBufferDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, impeller::Matrix::Translate(), impeller::VertexBuffer::vertex_buffer, and impeller::VertexBuffer::vertex_count.

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

## ◆ ImGui_ImplImpeller_Shutdown()

IMGUI_IMPL_API void ImGui_ImplImpeller_Shutdown | ( |  | ) |

Definition at line 132 of file imgui_impl_impeller.cc.

132 {
133 auto* bd = ImGui_ImplImpeller_GetBackendData();
134 IM_ASSERT(bd != nullptr &&
135 "No renderer backend to shutdown, or already shutdown?");
136 delete bd;
137 }

References ImGui_ImplImpeller_GetBackendData().

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