14 #include "impeller/playground/imgui/imgui_raster.frag.h"
15 #include "impeller/playground/imgui/imgui_raster.vert.h"
16 #include "third_party/imgui/imgui.h"
38 std::shared_ptr<impeller::Context>
context;
40 std::shared_ptr<impeller::Pipeline<impeller::PipelineDescriptor>>
pipeline;
41 std::shared_ptr<const impeller::Sampler>
sampler;
45 return ImGui::GetCurrentContext()
47 ImGui::GetIO().BackendRendererUserData)
52 const std::shared_ptr<impeller::Context>& context) {
53 ImGuiIO& io = ImGui::GetIO();
54 IM_ASSERT(io.BackendRendererUserData ==
nullptr &&
55 "Already initialized a renderer backend!");
59 io.BackendRendererUserData =
reinterpret_cast<void*
>(bd);
60 io.BackendRendererName =
"imgui_impl_impeller";
62 ImGuiBackendFlags_RendererHasVtxOffset;
66 bd->context = context;
70 unsigned char* pixels;
72 io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
77 texture_descriptor.size = {width, height};
78 texture_descriptor.mip_count = 1u;
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");
86 [[maybe_unused]]
bool uploaded = bd->font_texture->SetContents(
87 pixels, texture_descriptor.GetByteSizeOfBaseMipLevel());
89 "Could not upload ImGui font texture to device memory.");
95 impeller::ImguiRasterFragmentShader>::
96 MakeDefaultPipelineDescriptor(*context);
97 IM_ASSERT(desc.has_value() &&
"Could not create Impeller pipeline");
98 if (desc.has_value()) {
100 desc->ClearStencilAttachments();
101 desc->ClearDepthAttachment();
105 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
106 IM_ASSERT(bd->pipeline !=
nullptr &&
"Could not create ImGui pipeline.");
108 bd->sampler = context->GetSamplerLibrary()->GetSampler({});
109 IM_ASSERT(bd->pipeline !=
nullptr &&
"Could not create ImGui sampler.");
117 IM_ASSERT(bd !=
nullptr &&
118 "No renderer backend to shutdown, or already shutdown?");
124 if (draw_data->CmdListsCount == 0) {
128 using VS = impeller::ImguiRasterVertexShader;
129 using FS = impeller::ImguiRasterFragmentShader;
132 IM_ASSERT(bd !=
nullptr &&
"Did you call ImGui_ImplImpeller_Init()?");
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) {
142 buffer_desc.
size = total_vtx_bytes + total_idx_bytes;
145 auto buffer = bd->context->GetResourceAllocator()->CreateBuffer(buffer_desc);
150 draw_data->DisplaySize.x, draw_data->DisplaySize.y);
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)};
160 VS::UniformBuffer uniforms;
166 size_t vertex_buffer_offset = 0;
167 size_t index_buffer_offset = total_vtx_bytes;
169 for (
int draw_list_i = 0; draw_list_i < draw_data->CmdListsCount;
171 const ImDrawList* cmd_list = draw_data->CmdLists[draw_list_i];
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},
187 {color.x, color.y, color.z, color.w}});
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()),
196 vertex_buffer_offset)) {
197 IM_ASSERT(
false &&
"Could not copy vertices to buffer.");
199 if (!buffer->CopyHostBuffer(
200 reinterpret_cast<uint8_t*
>(cmd_list->IdxBuffer.Data),
202 IM_ASSERT(
false &&
"Could not copy indices to buffer.");
205 for (
int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
206 const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
208 if (pcmd->UserCallback) {
209 pcmd->UserCallback(cmd_list, pcmd);
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);
223 auto visible_clip = clip_rect.Intersection(viewport.rect);
224 if (!visible_clip.has_value()) {
227 clip_rect = visible_clip.value();
232 auto visible_clip = clip_rect.Intersection(
234 if (!visible_clip.has_value()) {
237 clip_rect = visible_clip.value();
243 draw_list_i, cmd_i));
249 VS::BindUniformBuffer(cmd, vtx_uniforms);
250 FS::BindTex(cmd, bd->font_texture, bd->sampler);
253 vertex_buffer_offset + pcmd->VtxOffset *
sizeof(ImDrawVert);
262 index_buffer_offset + pcmd->IdxOffset *
sizeof(ImDrawIdx),
263 pcmd->ElemCount *
sizeof(ImDrawIdx))};
273 vertex_buffer_offset += draw_list_vtx_bytes;
274 index_buffer_offset += draw_list_idx_bytes;