Flutter Engine
The Flutter Engine
Classes | Functions
imgui_impl_impeller.cc File Reference
#include "imgui_impl_impeller.h"
#include <algorithm>
#include <climits>
#include <memory>
#include <vector>
#include "impeller/core/host_buffer.h"
#include "impeller/core/platform.h"
#include "impeller/geometry/scalar.h"
#include "impeller/geometry/vector.h"
#include "impeller/playground/imgui/imgui_raster.frag.h"
#include "impeller/playground/imgui/imgui_raster.vert.h"
#include "third_party/imgui/imgui.h"
#include "impeller/core/allocator.h"
#include "impeller/core/formats.h"
#include "impeller/core/range.h"
#include "impeller/core/sampler.h"
#include "impeller/core/texture.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/core/vertex_buffer.h"
#include "impeller/geometry/matrix.h"
#include "impeller/geometry/point.h"
#include "impeller/geometry/rect.h"
#include "impeller/geometry/size.h"
#include "impeller/renderer/command.h"
#include "impeller/renderer/context.h"
#include "impeller/renderer/pipeline_builder.h"
#include "impeller/renderer/pipeline_descriptor.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/render_pass.h"

Go to the source code of this file.

Classes

struct  ImGui_ImplImpeller_Data
 

Functions

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

Function Documentation

◆ ImGui_ImplImpeller_GetBackendData()

static ImGui_ImplImpeller_Data * ImGui_ImplImpeller_GetBackendData ( )
static

Definition at line 49 of file imgui_impl_impeller.cc.

49 {
50 return ImGui::GetCurrentContext()
51 ? static_cast<ImGui_ImplImpeller_Data*>(
52 ImGui::GetIO().BackendRendererUserData)
53 : nullptr;
54}

◆ ImGui_ImplImpeller_Init()

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

Definition at line 56 of file imgui_impl_impeller.cc.

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

◆ ImGui_ImplImpeller_RenderDrawData()

void ImGui_ImplImpeller_RenderDrawData ( ImDrawData *  draw_data,
impeller::RenderPass render_pass 
)

Definition at line 126 of file imgui_impl_impeller.cc.

127 {
128 if (draw_data->CmdListsCount == 0) {
129 return; // Nothing to render.
130 }
131 auto host_buffer = impeller::HostBuffer::Create(
132 render_pass.GetContext()->GetResourceAllocator());
133
134 using VS = impeller::ImguiRasterVertexShader;
135 using FS = impeller::ImguiRasterFragmentShader;
136
138 IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplImpeller_Init()?");
139
140 size_t total_vtx_bytes = draw_data->TotalVtxCount * sizeof(VS::PerVertexData);
141 size_t total_idx_bytes = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
142 if (!total_vtx_bytes || !total_idx_bytes) {
143 return; // Nothing to render.
144 }
145
146 // Allocate buffer for vertices + indices.
148 buffer_desc.size = total_vtx_bytes + total_idx_bytes;
150
151 auto buffer = bd->context->GetResourceAllocator()->CreateBuffer(buffer_desc);
152 buffer->SetLabel(impeller::SPrintF("ImGui vertex+index buffer"));
153
154 auto display_rect = impeller::Rect::MakeXYWH(
155 draw_data->DisplayPos.x, draw_data->DisplayPos.y,
156 draw_data->DisplaySize.x, draw_data->DisplaySize.y);
157
158 auto viewport = impeller::Viewport{
159 .rect = display_rect.Scale(draw_data->FramebufferScale.x,
160 draw_data->FramebufferScale.y)};
161
162 // Allocate vertex shader uniform buffer.
163 VS::UniformBuffer uniforms;
164 uniforms.mvp = impeller::Matrix::MakeOrthographic(display_rect.GetSize())
165 .Translate(-display_rect.GetOrigin());
166 auto vtx_uniforms = host_buffer->EmplaceUniform(uniforms);
167
168 size_t vertex_buffer_offset = 0;
169 size_t index_buffer_offset = total_vtx_bytes;
170
171 for (int draw_list_i = 0; draw_list_i < draw_data->CmdListsCount;
172 draw_list_i++) {
173 const ImDrawList* cmd_list = draw_data->CmdLists[draw_list_i];
174
175 // Convert ImGui's per-vertex data (`ImDrawVert`) into the per-vertex data
176 // required by the shader (`VS::PerVectexData`). The only difference is that
177 // `ImDrawVert` uses an `int` for the color and the impeller shader uses 4
178 // floats.
179
180 // TODO(102778): Remove the need for this by adding support for attribute
181 // mapping of uint32s host-side to vec4s shader-side in
182 // impellerc.
183 std::vector<VS::PerVertexData> vtx_data;
184 vtx_data.reserve(cmd_list->VtxBuffer.size());
185 for (const auto& v : cmd_list->VtxBuffer) {
186 ImVec4 color = ImGui::ColorConvertU32ToFloat4(v.col);
187 vtx_data.push_back({{v.pos.x, v.pos.y}, //
188 {v.uv.x, v.uv.y}, //
189 {color.x, color.y, color.z, color.w}});
190 }
191
192 auto draw_list_vtx_bytes =
193 static_cast<size_t>(vtx_data.size() * sizeof(VS::PerVertexData));
194 auto draw_list_idx_bytes =
195 static_cast<size_t>(cmd_list->IdxBuffer.size_in_bytes());
196 if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vtx_data.data()),
197 impeller::Range{0, draw_list_vtx_bytes},
198 vertex_buffer_offset)) {
199 IM_ASSERT(false && "Could not copy vertices to buffer.");
200 }
201 if (!buffer->CopyHostBuffer(
202 reinterpret_cast<uint8_t*>(cmd_list->IdxBuffer.Data),
203 impeller::Range{0, draw_list_idx_bytes}, index_buffer_offset)) {
204 IM_ASSERT(false && "Could not copy indices to buffer.");
205 }
206
207 for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
208 const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
209
210 if (pcmd->UserCallback) {
211 pcmd->UserCallback(cmd_list, pcmd);
212 } else {
213 // Make the clip rect relative to the viewport.
214 auto clip_rect = impeller::Rect::MakeLTRB(
215 (pcmd->ClipRect.x - draw_data->DisplayPos.x) *
216 draw_data->FramebufferScale.x,
217 (pcmd->ClipRect.y - draw_data->DisplayPos.y) *
218 draw_data->FramebufferScale.y,
219 (pcmd->ClipRect.z - draw_data->DisplayPos.x) *
220 draw_data->FramebufferScale.x,
221 (pcmd->ClipRect.w - draw_data->DisplayPos.y) *
222 draw_data->FramebufferScale.y);
223 {
224 // Clamp the clip to the viewport bounds.
225 auto visible_clip = clip_rect.Intersection(viewport.rect);
226 if (!visible_clip.has_value()) {
227 continue; // Nothing to render.
228 }
229 clip_rect = visible_clip.value();
230 }
231 {
232 // Clamp the clip to ensure it never goes outside of the render
233 // target.
234 auto visible_clip = clip_rect.Intersection(
236 if (!visible_clip.has_value()) {
237 continue; // Nothing to render.
238 }
239 clip_rect = visible_clip.value();
240 }
241
243 "ImGui draw list %d (command %d)", draw_list_i, cmd_i));
244 render_pass.SetViewport(viewport);
245 render_pass.SetScissor(impeller::IRect::RoundOut(clip_rect));
246 render_pass.SetPipeline(bd->pipeline);
247 VS::BindUniformBuffer(render_pass, vtx_uniforms);
248 FS::BindTex(render_pass, bd->font_texture, bd->sampler);
249
250 size_t vb_start =
251 vertex_buffer_offset + pcmd->VtxOffset * sizeof(ImDrawVert);
252
253 impeller::VertexBuffer vertex_buffer;
254 vertex_buffer.vertex_buffer = {
255 .buffer = buffer,
256 .range = impeller::Range(vb_start, draw_list_vtx_bytes - vb_start)};
257 vertex_buffer.index_buffer = {
258 .buffer = buffer,
259 .range = impeller::Range(
260 index_buffer_offset + pcmd->IdxOffset * sizeof(ImDrawIdx),
261 pcmd->ElemCount * sizeof(ImDrawIdx))};
262 vertex_buffer.vertex_count = pcmd->ElemCount;
264 render_pass.SetVertexBuffer(std::move(vertex_buffer));
265 render_pass.SetBaseVertex(pcmd->VtxOffset);
266
267 render_pass.Draw().ok();
268 }
269 }
270
271 vertex_buffer_offset += draw_list_vtx_bytes;
272 index_buffer_offset += draw_list_idx_bytes;
273 }
274 host_buffer->Reset();
275}
bool ok() const
Definition: status.h:71
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator)
Definition: host_buffer.cc:20
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
Definition: render_pass.cc:123
virtual void SetPipeline(const std::shared_ptr< Pipeline< PipelineDescriptor > > &pipeline)
The pipeline to use for this command.
Definition: render_pass.cc:92
virtual void SetScissor(IRect scissor)
Definition: render_pass.cc:115
ISize GetRenderTargetSize() const
Definition: render_pass.cc:43
virtual fml::Status Draw()
Record the currently pending command.
Definition: render_pass.cc:127
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
Definition: render_pass.cc:97
const std::shared_ptr< const Context > & GetContext() const
Definition: render_pass.cc:88
virtual void SetBaseVertex(uint64_t value)
Definition: render_pass.cc:107
virtual void SetViewport(Viewport viewport)
Definition: render_pass.cc:111
DlColor color
static ImGui_ImplImpeller_Data * ImGui_ImplImpeller_GetBackendData()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
SolidFillVertexShader VS
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
std::shared_ptr< const DeviceBuffer > buffer
Definition: buffer_view.h:16
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:497
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:240
RoundOut(const TRect< U > &r)
Definition: rect.h:666
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
constexpr TRect Scale(Type scale) const
Definition: rect.h:192
static constexpr TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
BufferView index_buffer
The index buffer binding used by the vertex shader stage.
Definition: vertex_buffer.h:18

◆ ImGui_ImplImpeller_Shutdown()

void ImGui_ImplImpeller_Shutdown ( )

Definition at line 119 of file imgui_impl_impeller.cc.

119 {
121 IM_ASSERT(bd != nullptr &&
122 "No renderer backend to shutdown, or already shutdown?");
123 delete bd;
124}