Flutter Engine
 
Loading...
Searching...
No Matches
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

namespace  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;
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}
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
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...
constexpr size_t GetByteSizeOfBaseMipLevel() const

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel(), height, impeller::kDevicePrivate, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::mip_count, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and width.

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
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.
160 buffer_desc.size = total_vtx_bytes + total_idx_bytes;
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;
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}
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
Definition host_buffer.h:47
void Reset()
Resets the contents of the HostBuffer to nothing so it can be reused.
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 disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
LinePipeline::FragmentShader FS
LinePipeline::VertexShader VS
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition matrix.h:633
constexpr Matrix Translate(const Vector3 &t) const
Definition matrix.h:263
RoundOut(const TRect< U > &r)
Definition rect.h:679
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:202
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
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.

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(), fml::Status::ok(), 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 {
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().