13 #include "fml/mapping.h"
18 #include "impeller/playground/imgui/imgui_raster.frag.h"
19 #include "impeller/playground/imgui/imgui_raster.vert.h"
20 #include "third_party/imgui/imgui.h"
44 std::shared_ptr<impeller::Context>
context;
46 std::shared_ptr<impeller::Pipeline<impeller::PipelineDescriptor>>
pipeline;
51 return ImGui::GetCurrentContext()
53 ImGui::GetIO().BackendRendererUserData)
58 const std::shared_ptr<impeller::Context>& context) {
59 ImGuiIO& io = ImGui::GetIO();
60 IM_ASSERT(io.BackendRendererUserData ==
nullptr &&
61 "Already initialized a renderer backend!");
66 io.BackendRendererUserData =
reinterpret_cast<void*
>(bd);
67 io.BackendRendererName =
"imgui_impl_impeller";
69 ImGuiBackendFlags_RendererHasVtxOffset;
73 bd->context = context;
77 unsigned char* pixels;
79 io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
84 texture_descriptor.
size = {width, height};
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");
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),
99 context->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
103 blit_pass->EncodeCommands();
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.");
114 impeller::ImguiRasterFragmentShader>::
115 MakeDefaultPipelineDescriptor(*context);
116 IM_ASSERT(desc.has_value() &&
"Could not create Impeller pipeline");
117 if (desc.has_value()) {
119 desc->ClearStencilAttachments();
120 desc->ClearDepthAttachment();
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.");
134 IM_ASSERT(bd !=
nullptr &&
135 "No renderer backend to shutdown, or already shutdown?");
142 if (draw_data->CmdListsCount == 0) {
146 using VS = impeller::ImguiRasterVertexShader;
147 using FS = impeller::ImguiRasterFragmentShader;
150 IM_ASSERT(bd !=
nullptr &&
"Did you call ImGui_ImplImpeller_Init()?");
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) {
160 buffer_desc.
size = total_vtx_bytes + total_idx_bytes;
163 auto buffer = bd->context->GetResourceAllocator()->CreateBuffer(buffer_desc);
164 buffer->SetLabel(
"ImGui vertex+index buffer");
167 draw_data->DisplayPos.x, draw_data->DisplayPos.y,
168 draw_data->DisplaySize.x, draw_data->DisplaySize.y);
171 .
rect = display_rect.
Scale(draw_data->FramebufferScale.x,
172 draw_data->FramebufferScale.y)};
175 VS::UniformBuffer uniforms;
180 size_t vertex_buffer_offset = 0;
181 size_t index_buffer_offset = total_vtx_bytes;
183 for (
int draw_list_i = 0; draw_list_i < draw_data->CmdListsCount;
185 const ImDrawList* cmd_list = draw_data->CmdLists[draw_list_i];
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},
201 {color.x, color.y, color.z, color.w}});
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()),
210 vertex_buffer_offset)) {
211 IM_ASSERT(
false &&
"Could not copy vertices to buffer.");
213 if (!buffer->CopyHostBuffer(
214 reinterpret_cast<uint8_t*
>(cmd_list->IdxBuffer.Data),
216 IM_ASSERT(
false &&
"Could not copy indices to buffer.");
219 for (
int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
220 const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
222 if (pcmd->UserCallback) {
223 pcmd->UserCallback(cmd_list, pcmd);
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);
237 auto visible_clip = clip_rect.Intersection(viewport.rect);
238 if (!visible_clip.has_value()) {
241 clip_rect = visible_clip.value();
246 auto visible_clip = clip_rect.Intersection(
248 if (!visible_clip.has_value()) {
251 clip_rect = visible_clip.value();
255 std::format(
"ImGui draw list {} (command {})", draw_list_i, cmd_i));
259 VS::BindUniformBuffer(render_pass, vtx_uniforms);
260 FS::BindTex(render_pass, bd->font_texture, bd->sampler);
263 vertex_buffer_offset + pcmd->VtxOffset *
sizeof(ImDrawVert);
270 pcmd->IdxOffset *
sizeof(ImDrawIdx),
271 pcmd->ElemCount *
sizeof(ImDrawIdx)));
277 render_pass.
Draw().ok();
281 vertex_buffer_offset += draw_list_vtx_bytes;
282 index_buffer_offset += draw_list_idx_bytes;
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
void Reset()
Resets the contents of the HostBuffer to nothing so it can be reused.
Render passes encode render commands directed as one specific render target into an underlying comman...
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
virtual void SetScissor(IRect32 scissor)
virtual void SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
ISize GetRenderTargetSize() const
virtual fml::Status Draw()
Record the currently pending command.
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
virtual void SetBaseVertex(uint64_t value)
virtual void SetViewport(Viewport viewport)
void ImGui_ImplImpeller_RenderDrawData(ImDrawData *draw_data, impeller::RenderPass &render_pass, impeller::HostBuffer &host_buffer)
bool ImGui_ImplImpeller_Init(const std::shared_ptr< impeller::Context > &context)
static ImGui_ImplImpeller_Data * ImGui_ImplImpeller_GetBackendData()
void ImGui_ImplImpeller_Shutdown()
LinePipeline::FragmentShader FS
LinePipeline::VertexShader VS
std::shared_ptr< impeller::Context > context
std::shared_ptr< impeller::Pipeline< impeller::PipelineDescriptor > > pipeline
std::shared_ptr< impeller::Texture > font_texture
impeller::raw_ptr< const impeller::Sampler > sampler
ImGui_ImplImpeller_Data(impeller::raw_ptr< const impeller::Sampler > p_sampler)
static constexpr Matrix MakeOrthographic(TSize< T > size)
constexpr Matrix Translate(const Vector3 &t) const
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
RoundOut(const TRect< U > &r)
constexpr TRect Scale(Type scale) const
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr static TRect MakeSize(const TSize< U > &size)
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
constexpr size_t GetByteSizeOfBaseMipLevel() const
BufferView index_buffer
The index buffer binding used by the vertex shader stage.