12 #include "fml/mapping.h"
17 #include "impeller/playground/imgui/imgui_raster.frag.h"
18 #include "impeller/playground/imgui/imgui_raster.vert.h"
19 #include "third_party/imgui/imgui.h"
43 std::shared_ptr<impeller::Context>
context;
45 std::shared_ptr<impeller::Pipeline<impeller::PipelineDescriptor>>
pipeline;
50 return ImGui::GetCurrentContext()
52 ImGui::GetIO().BackendRendererUserData)
57 const std::shared_ptr<impeller::Context>& context) {
58 ImGuiIO& io = ImGui::GetIO();
59 IM_ASSERT(io.BackendRendererUserData ==
nullptr &&
60 "Already initialized a renderer backend!");
65 io.BackendRendererUserData =
reinterpret_cast<void*
>(bd);
66 io.BackendRendererName =
"imgui_impl_impeller";
68 ImGuiBackendFlags_RendererHasVtxOffset;
72 bd->context = context;
76 unsigned char* pixels;
78 io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
83 texture_descriptor.
size = {width, height};
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");
92 auto command_buffer = context->CreateCommandBuffer();
93 auto blit_pass = command_buffer->CreateBlitPass();
94 auto mapping = std::make_shared<fml::NonOwnedMapping>(
95 reinterpret_cast<const uint8_t*
>(pixels),
98 context->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
102 blit_pass->EncodeCommands();
104 [[maybe_unused]]
bool uploaded =
105 context->GetCommandQueue()->Submit({command_buffer}).ok();
106 IM_ASSERT(uploaded &&
107 "Could not upload ImGui font texture to device memory.");
113 impeller::ImguiRasterFragmentShader>::
114 MakeDefaultPipelineDescriptor(*context);
115 IM_ASSERT(desc.has_value() &&
"Could not create Impeller pipeline");
116 if (desc.has_value()) {
118 desc->ClearStencilAttachments();
119 desc->ClearDepthAttachment();
123 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
124 IM_ASSERT(bd->pipeline !=
nullptr &&
"Could not create ImGui pipeline.");
125 IM_ASSERT(bd->pipeline !=
nullptr &&
"Could not create ImGui sampler.");
133 IM_ASSERT(bd !=
nullptr &&
134 "No renderer backend to shutdown, or already shutdown?");
141 if (draw_data->CmdListsCount == 0) {
145 using VS = impeller::ImguiRasterVertexShader;
146 using FS = impeller::ImguiRasterFragmentShader;
149 IM_ASSERT(bd !=
nullptr &&
"Did you call ImGui_ImplImpeller_Init()?");
151 size_t total_vtx_bytes = draw_data->TotalVtxCount *
sizeof(VS::PerVertexData);
152 size_t total_idx_bytes = draw_data->TotalIdxCount *
sizeof(ImDrawIdx);
153 if (!total_vtx_bytes || !total_idx_bytes) {
159 buffer_desc.
size = total_vtx_bytes + total_idx_bytes;
162 auto buffer = bd->context->GetResourceAllocator()->CreateBuffer(buffer_desc);
166 draw_data->DisplayPos.x, draw_data->DisplayPos.y,
167 draw_data->DisplaySize.x, draw_data->DisplaySize.y);
170 .
rect = display_rect.
Scale(draw_data->FramebufferScale.x,
171 draw_data->FramebufferScale.y)};
174 VS::UniformBuffer uniforms;
179 size_t vertex_buffer_offset = 0;
180 size_t index_buffer_offset = total_vtx_bytes;
182 for (
int draw_list_i = 0; draw_list_i < draw_data->CmdListsCount;
184 const ImDrawList* cmd_list = draw_data->CmdLists[draw_list_i];
194 std::vector<VS::PerVertexData> vtx_data;
195 vtx_data.reserve(cmd_list->VtxBuffer.size());
196 for (
const auto& v : cmd_list->VtxBuffer) {
197 ImVec4 color = ImGui::ColorConvertU32ToFloat4(v.col);
198 vtx_data.push_back({{v.pos.x, v.pos.y},
200 {color.x, color.y, color.z, color.w}});
203 auto draw_list_vtx_bytes =
204 static_cast<size_t>(vtx_data.size() *
sizeof(VS::PerVertexData));
205 auto draw_list_idx_bytes =
206 static_cast<size_t>(cmd_list->IdxBuffer.size_in_bytes());
207 if (!buffer->CopyHostBuffer(
reinterpret_cast<uint8_t*
>(vtx_data.data()),
209 vertex_buffer_offset)) {
210 IM_ASSERT(
false &&
"Could not copy vertices to buffer.");
212 if (!buffer->CopyHostBuffer(
213 reinterpret_cast<uint8_t*
>(cmd_list->IdxBuffer.Data),
215 IM_ASSERT(
false &&
"Could not copy indices to buffer.");
218 for (
int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
219 const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
221 if (pcmd->UserCallback) {
222 pcmd->UserCallback(cmd_list, pcmd);
226 (pcmd->ClipRect.x - draw_data->DisplayPos.x) *
227 draw_data->FramebufferScale.x,
228 (pcmd->ClipRect.y - draw_data->DisplayPos.y) *
229 draw_data->FramebufferScale.y,
230 (pcmd->ClipRect.z - draw_data->DisplayPos.x) *
231 draw_data->FramebufferScale.x,
232 (pcmd->ClipRect.w - draw_data->DisplayPos.y) *
233 draw_data->FramebufferScale.y);
236 auto visible_clip = clip_rect.Intersection(viewport.rect);
237 if (!visible_clip.has_value()) {
240 clip_rect = visible_clip.value();
245 auto visible_clip = clip_rect.Intersection(
247 if (!visible_clip.has_value()) {
250 clip_rect = visible_clip.value();
254 "ImGui draw list %d (command %d)", draw_list_i, cmd_i));
258 VS::BindUniformBuffer(render_pass, vtx_uniforms);
259 FS::BindTex(render_pass, bd->font_texture, bd->sampler);
262 vertex_buffer_offset + pcmd->VtxOffset *
sizeof(ImDrawVert);
269 pcmd->IdxOffset *
sizeof(ImDrawIdx),
270 pcmd->ElemCount *
sizeof(ImDrawIdx)));
276 render_pass.
Draw().ok();
280 vertex_buffer_offset += draw_list_vtx_bytes;
281 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(IRect 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()
std::string SPrintF(const char *format,...)
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.