| Flutter Impeller |

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_Data * | ImGui_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 }

Referenced by ImGui_ImplImpeller_RenderDrawData(), and ImGui_ImplImpeller_Shutdown().

## ◆ 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{};
81 texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
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 }

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

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

## ◆ 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
137 auto* bd = ImGui_ImplImpeller_GetBackendData();
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.
147 impeller::DeviceBufferDescriptor buffer_desc;
148 buffer_desc.size = total_vtx_bytes + total_idx_bytes;
149 buffer_desc.storage_mode = impeller::StorageMode::kHostVisible;
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(
235 impeller::Rect::MakeSize(render_pass.GetRenderTargetSize()));
236 if (!visible_clip.has_value()) {
237 continue; // Nothing to render.
238 }
239 clip_rect = visible_clip.value();
240 }
241
242 render_pass.SetCommandLabel(impeller::SPrintF(
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;
263 vertex_buffer.index_type = impeller::IndexType::k16bit;
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 }

References impeller::BufferView::buffer, color, impeller::HostBuffer::Create(), impeller::RenderPass::Draw(), impeller::RenderPass::GetContext(), 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::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::SPrintF(), impeller::DeviceBufferDescriptor::storage_mode, impeller::Matrix::Translate(), impeller::VertexBuffer::vertex_buffer, and impeller::VertexBuffer::vertex_count.

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

## ◆ ImGui_ImplImpeller_Shutdown()

void ImGui_ImplImpeller_Shutdown | ( |  | ) |

Definition at line 119 of file imgui_impl_impeller.cc.

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

References ImGui_ImplImpeller_GetBackendData().

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

impeller::VertexBuffer::index_type
IndexType index_type
Definition: vertex_buffer.h:29
impeller::IndexType::k16bit
@ k16bit
impeller::Viewport::rect
Rect rect
Definition: formats.h:404
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:14
impeller::VertexBuffer
Definition: vertex_buffer.h:13
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::HostBuffer::Create
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator)
Definition: host_buffer.cc:21
impeller::RenderPass::SetVertexBuffer
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
Definition: render_pass.cc:123
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:16
ImGui_ImplImpeller_GetBackendData
static ImGui_ImplImpeller_Data * ImGui_ImplImpeller_GetBackendData()
Definition: imgui_impl_impeller.cc:49
impeller::VertexBuffer::vertex_buffer
BufferView vertex_buffer
Definition: vertex_buffer.h:14
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::VertexBuffer::vertex_count
size_t vertex_count
Definition: vertex_buffer.h:23
impeller::RenderPass::SetCommandLabel
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
Definition: render_pass.cc:97
impeller::RenderPass::Draw
virtual fml::Status Draw()
Record the currently pending command.
Definition: render_pass.cc:127
impeller::TRect::RoundOut
RoundOut(const TRect< U > &r)
Definition: rect.h:673
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:16
impeller::RenderPass::GetRenderTargetSize
ISize GetRenderTargetSize() const
Definition: render_pass.cc:43
impeller::RenderPass::SetViewport
virtual void SetViewport(Viewport viewport)
Definition: render_pass.cc:111
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::DeviceBufferDescriptor::storage_mode
StorageMode storage_mode
Definition: device_buffer_descriptor.h:15
impeller::Matrix::Translate
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:240
impeller::TRect::Scale
constexpr TRect Scale(Type scale) const
Definition: rect.h:196
impeller::RenderPass::SetScissor
virtual void SetScissor(IRect scissor)
Definition: render_pass.cc:115
impeller::Viewport
Definition: formats.h:403
impeller::VertexBuffer::index_buffer
BufferView index_buffer
The index buffer binding used by the vertex shader stage.
Definition: vertex_buffer.h:18
impeller::Range
Definition: range.h:13
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
impeller::BufferView::buffer
std::shared_ptr< const DeviceBuffer > buffer
Definition: buffer_view.h:16
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:523
color
DlColor color
Definition: dl_golden_blur_unittests.cc:24
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:39
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::RenderPass::SetPipeline
virtual void SetPipeline(const std::shared_ptr< Pipeline< PipelineDescriptor >> &pipeline)
The pipeline to use for this command.
Definition: render_pass.cc:92
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::PipelineBuilder
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
Definition: pipeline_builder.h:30
ImGui_ImplImpeller_Data
Definition: imgui_impl_impeller.cc:38
impeller::RenderPass::GetContext
const std::shared_ptr< const Context > & GetContext() const
Definition: render_pass.cc:88
impeller::RenderPass::SetBaseVertex
virtual void SetBaseVertex(uint64_t value)
Definition: render_pass.cc:107