6 #include <imgui_freetype.h> 37 if (frameData.vertexMemoryPtr) {
38 frameData.vertexMemory.unmap();
41 if (frameData.indexMemoryPtr) {
42 frameData.indexMemory.unmap();
45 for (
const auto& descriptorSet : frameData.texturesDescriptorSets) {
66 bool Gui::init(
const std::vector<API::ImageView>& imageViews) {
67 ImGuiIO& io = ImGui::GetIO();
70 if (!io.Fonts->Fonts.Size) {
71 io.Fonts->AddFontDefault();
77 io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
85 LUG_LOG.error(
"Gui::init: Can't find graphic queue");
93 VkResult result{VK_SUCCESS};
96 LUG_LOG.error(
"Gui::init: Can't create a command pool: {}", result);
102 commandBufferBuilder.
setLevel(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
105 std::vector<Vulkan::API::CommandBuffer> commandBuffers(imageViews.size());
109 VkResult result{VK_SUCCESS};
110 if (!commandBufferBuilder.build(commandBuffers, &result)) {
111 LUG_LOG.error(
"Gui::init: Can't create the command buffer: {}", result);
118 for (uint32_t i = 0; i < imageViews.size(); ++i) {
119 _framesData[i].commandBuffer = std::move(commandBuffers[i]);
121 commandBuffers.clear();
132 ImGuiIO& io = ImGui::GetIO();
157 ImGuiIO& io = ImGui::GetIO();
160 unsigned char* fontData =
nullptr;
161 uint32_t texWidth = 0;
162 uint32_t texHeight = 0;
168 unsigned int flags = ImGuiFreeType::NoHinting;
169 ImGuiFreeType::BuildFontAtlas(io.Fonts, flags);
170 io.Fonts->GetTexDataAsRGBA32(&fontData, &tempWidth, &tempHeight);
171 texWidth =
static_cast<uint32_t
>(tempWidth);
172 texHeight =
static_cast<uint32_t
>(tempHeight);
181 LUG_LOG.error(
"Gui::initFontsTexture: Can't find transfer queue");
188 VkResult result{ VK_SUCCESS };
191 LUG_LOG.error(
"Gui::initFontsTexture: Can't create a command pool: {}", result);
201 LUG_LOG.error(
"Gui::initFontsTexture: Can't load fonts texture");
210 LUG_LOG.error(
"Gui::initFontsTexture Can't create fonts texture");
219 LUG_LOG.error(
"Gui::initFontsTexture: Failed to init frame data");
233 if (!graphicsPipelineBuilder.setShaderFromFile(VK_SHADER_STAGE_VERTEX_BIT,
"main",
_renderer.
getInfo().
shadersRoot +
"gui.vert.spv")
234 || !graphicsPipelineBuilder.setShaderFromFile(VK_SHADER_STAGE_FRAGMENT_BIT,
"main",
_renderer.
getInfo().
shadersRoot +
"gui.frag.spv")) {
235 LUG_LOG.error(
"ForwardRenderer: Can't create pipeline's shaders.");
240 auto vertexBinding = graphicsPipelineBuilder.addInputBinding(
sizeof(ImDrawVert), VK_VERTEX_INPUT_RATE_VERTEX);
242 vertexBinding.addAttributes(VK_FORMAT_R32G32B32_SFLOAT, offsetof(ImDrawVert, pos));
243 vertexBinding.addAttributes(VK_FORMAT_R32G32_SFLOAT, offsetof(ImDrawVert, uv));
244 vertexBinding.addAttributes(VK_FORMAT_R8G8B8A8_UNORM, offsetof(ImDrawVert, col));
247 const VkViewport viewport{
256 const VkRect2D scissor{
261 auto viewportState = graphicsPipelineBuilder.getViewportState();
262 viewportState.addViewport(viewport);
263 viewportState.addScissor(scissor);
266 auto rasterizationState = graphicsPipelineBuilder.getRasterizationState();
267 rasterizationState.setCullMode(VK_CULL_MODE_NONE);
270 const VkPipelineColorBlendAttachmentState colorBlendAttachment{
272 VK_BLEND_FACTOR_SRC_ALPHA,
273 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
275 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
276 VK_BLEND_FACTOR_ZERO,
278 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
281 auto colorBlendState = graphicsPipelineBuilder.getColorBlendState();
282 colorBlendState.addAttachment(colorBlendAttachment);
285 graphicsPipelineBuilder.setDynamicStates({
286 VK_DYNAMIC_STATE_VIEWPORT,
287 VK_DYNAMIC_STATE_SCISSOR
290 std::vector<Vulkan::API::DescriptorSetLayout> descriptorSetLayouts;
297 const VkDescriptorSetLayoutBinding binding{
299 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
301 VK_SHADER_STAGE_FRAGMENT_BIT,
305 descriptorSetLayoutBuilder.
setBindings({ binding });
308 VkResult result{VK_SUCCESS};
309 descriptorSetLayouts.resize(1);
310 if (!descriptorSetLayoutBuilder.
build(descriptorSetLayouts[0], &result)) {
311 LUG_LOG.error(
"Gui::initPipeline: Can't create pipeline descriptor: {}", result);
316 VkPushConstantRange pushConstant{
317 VK_SHADER_STAGE_VERTEX_BIT,
324 pipelineLayoutBuilder.setPushConstants({ pushConstant });
325 pipelineLayoutBuilder.setDescriptorSetLayouts(std::move(descriptorSetLayouts));
327 VkResult result{VK_SUCCESS};
329 LUG_LOG.error(
"Gui::initPipeline: Can't create pipeline layout: {}", result);
341 const VkAttachmentDescription colorAttachment{
344 VK_SAMPLE_COUNT_1_BIT,
345 VK_ATTACHMENT_LOAD_OP_LOAD,
346 VK_ATTACHMENT_STORE_OP_STORE,
347 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
348 VK_ATTACHMENT_STORE_OP_DONT_CARE,
349 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
350 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
353 auto colorAttachmentIndex = renderPassBuilder.addAttachment(colorAttachment);
356 VK_PIPELINE_BIND_POINT_GRAPHICS,
358 { { colorAttachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } },
364 renderPassBuilder.addSubpass(subpassDescription);
366 VkResult result{VK_SUCCESS};
368 if (!renderPassBuilder.build(renderPass, &result)) {
369 LUG_LOG.error(
"Gui::initPipeline: Can't create render pass: {}", result);
373 graphicsPipelineBuilder.setRenderPass(std::move(renderPass), 0);
376 VkResult result{VK_SUCCESS};
377 if (!graphicsPipelineBuilder.build(
_pipeline, &result)) {
378 LUG_LOG.error(
"Gui::initPipeline: Can't create pipeline: {}", result);
388 for (
size_t i = 0; i < imageViews.size(); ++i) {
393 framebufferBuilder.addAttachment(&imageViews[i]);
394 framebufferBuilder.setWidth(imageViews[i].getImage()->getExtent().width);
395 framebufferBuilder.setHeight(imageViews[i].getImage()->getExtent().height);
397 VkResult result{VK_SUCCESS};
398 if (!framebufferBuilder.build(
_framesData[i].framebuffer, &result)) {
399 LUG_LOG.error(
"Gui::initFramebuffers: Can't create framebuffer: {}", result);
408 ImGuiIO& io = ImGui::GetIO();
413 #if defined(LUG_SYSTEM_ANDROID) 418 io.MousePos = ImVec2(static_cast<float>(mousePos.x()), static_cast<float>(mousePos.y()));
424 bool Gui::endFrame(
const std::vector<VkSemaphore>& waitSemaphores, uint32_t currentImageIndex) {
433 LUG_LOG.error(
"Gui::endFrame: Failed to update buffers");
440 ImGuiIO& io = ImGui::GetIO();
446 const VkViewport vkViewport{
473 if (static_cast<VkBuffer>(frameData.
vertexBuffer) != VK_NULL_HANDLE) {
477 if (static_cast<VkBuffer>(frameData.
indexBuffer) != VK_NULL_HANDLE) {
483 {2.0f / io.DisplaySize.x, 2.0f / io.DisplaySize.y},
486 const API::CommandBuffer::CmdPushConstants cmdPushConstants{
488 VK_SHADER_STAGE_VERTEX_BIT,
497 std::vector<const Render::DescriptorSetPool::DescriptorSet*> texturesDescriptorSets;
500 ImDrawData* imDrawData = ImGui::GetDrawData();
502 uint32_t vertexCount = 0;
503 uint32_t indexCount = 0;
505 for (int32_t i = 0; i < imDrawData->CmdListsCount; i++) {
506 const ImDrawList* cmd_list = imDrawData->CmdLists[i];
507 for (int32_t j = 0; j < cmd_list->CmdBuffer.Size; j++) {
508 const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[j];
510 const VkRect2D scissor{
512 std::max(static_cast<int32_t>(pcmd->ClipRect.x), 0),
513 std::max(static_cast<int32_t>(pcmd->ClipRect.y), 0)},
515 static_cast<uint32_t
>(pcmd->ClipRect.z - pcmd->ClipRect.x),
516 static_cast<uint32_t>(pcmd->ClipRect.w - pcmd->ClipRect.y)
527 if (!texturesDescriptorSet) {
528 LUG_LOG.error(
"Gui::endFrame: Can't allocate textures descriptor set");
532 texturesDescriptorSets.push_back(texturesDescriptorSet);
536 const API::CommandBuffer::CmdBindDescriptors texturesBind{
538 VK_PIPELINE_BIND_POINT_GRAPHICS,
547 const API::CommandBuffer::CmdDrawIndexed cmdDrawIndexed {
556 indexCount += pcmd->ElemCount;
558 vertexCount += cmd_list->VtxBuffer.Size;
573 std::vector<VkPipelineStageFlags> waitDstStageMasks(waitSemaphores.size(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
574 if (
_graphicQueue->
submit(frameData.
commandBuffer, { static_cast<VkSemaphore>(frameData.semaphore) }, waitSemaphores, waitDstStageMasks, static_cast<VkFence>(frameData.
fence)) ==
false) {
575 LUG_LOG.error(
"GUI: Can't submit commandBuffer");
583 ImGuiIO& io = ImGui::GetIO();
585 if (io.WantCaptureMouse) {
609 io.MouseWheel +=
static_cast<float>(
event.mouse.scrollOffset.xOffset);
614 + ((
event.touchScreen.coordinates[0].y() - io.MousePosPrev.y) * (event.
touchScreen.
coordinates[0].y() - io.MousePosPrev.y)));
615 if ((static_cast<float>(io.MousePosPrev.y) -
event.touchScreen.coordinates[0].y()) > 0) {
616 io.MouseWheel -= draggedDistance / (io.DisplaySize.y -
static_cast<float>(io.MousePosPrev.y));
618 io.MouseWheel += draggedDistance / (io.DisplaySize.y -
static_cast<float>(io.MousePosPrev.y));
625 if (io.WantCaptureKeyboard) {
630 io.KeyCtrl =
static_cast<int>(
event.key.ctrl);
631 io.KeyShift =
static_cast<int>(
event.key.shift);
632 io.KeyAlt =
static_cast<int>(
event.key.alt);
633 io.KeySuper =
static_cast<int>(
event.key.system);
636 io.AddInputCharacter(static_cast<unsigned short>(event.
character.
val));
651 ImDrawData* imDrawData = ImGui::GetDrawData();
653 LUG_LOG.error(
"Gui::updateBuffers: Failed to retrieve draw data from imgui");
657 if (imDrawData->TotalVtxCount == 0 || imDrawData->TotalIdxCount == 0) {
665 const VkDeviceSize vertexBufferSize = imDrawData->TotalVtxCount *
sizeof(ImDrawVert);
666 const VkDeviceSize indexBufferSize = imDrawData->TotalIdxCount *
sizeof(ImDrawIdx);
677 bufferBuilder.
setSize(vertexBufferSize);
678 bufferBuilder.
setUsage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
680 VkResult result{VK_SUCCESS};
682 LUG_LOG.error(
"Gui::updateBuffers: Can't create staging buffer: {}", result);
692 deviceMemoryBuilder.
setMemoryFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
695 VkResult result{VK_SUCCESS};
697 LUG_LOG.error(
"Gui::updateBuffers: Can't create staging buffer device memory: {}", result);
712 bufferBuilder.
setSize(indexBufferSize);
713 bufferBuilder.
setUsage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
715 VkResult result{VK_SUCCESS};
717 LUG_LOG.error(
"Gui::updateBuffers: Can't create staging buffer: {}", result);
727 deviceMemoryBuilder.
setMemoryFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
730 VkResult result{VK_SUCCESS};
732 LUG_LOG.error(
"Gui::updateBuffers: Can't create staging buffer device memory: {}", result);
743 ImDrawVert* vertexMemoryPtr =
static_cast<ImDrawVert*
>(frameData.
vertexMemoryPtr);
744 ImDrawIdx* indexMemoryPtr =
static_cast<ImDrawIdx*
>(frameData.
indexMemoryPtr);
746 for (
int n = 0; n < imDrawData->CmdListsCount; n++) {
747 const ImDrawList* cmd_list = imDrawData->CmdLists[n];
748 memcpy(vertexMemoryPtr, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size *
sizeof(ImDrawVert));
749 memcpy(indexMemoryPtr, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size *
sizeof(ImDrawIdx));
750 vertexMemoryPtr += cmd_list->VtxBuffer.Size;
751 indexMemoryPtr += cmd_list->IdxBuffer.Size;
767 VkResult result{ VK_SUCCESS };
768 if (!semaphoreBuilder.
build(frameData.semaphore, &result)) {
769 LUG_LOG.error(
"Gui::initFontsTexture: Can't create semaphore: {}", result);
777 fenceBuilder.
setFlags(VK_FENCE_CREATE_SIGNALED_BIT);
779 VkResult result{ VK_SUCCESS };
780 if (!fenceBuilder.
build(frameData.fence, &result)) {
781 LUG_LOG.error(
"Gui::initFontsTexture: Can't create fence: {}", result);
const RenderPass * getRenderPass() const
bool reset(bool releaseRessources=false) const
Gui(lug::Graphics::Vulkan::Renderer &renderer, lug::Graphics::Vulkan::Render::Window &window)
TouchScreenEvent _touchScreenState
const API::Queue * _graphicQueue
bool build(API::DeviceMemory &instance, VkResult *returnResult=nullptr)
const API::Queue * _transferQueue
lug::Math::Vec2f coordinates[2]
The Touch coordinate.
const API::DescriptorSet & getDescriptorSet() const
void beginFrame(const lug::System::Time &elapsedTime)
void setBindings(const std::vector< VkDescriptorSetLayoutBinding > &bindings)
const Math::Vec2i & getMousePos() const
Retrieves the mouses position.
void setFlags(VkFenceCreateFlags flags)
void setMinFilter(Render::Texture::Filter minFilter)
bool build(API::Semaphore &instance, VkResult *returnResult=nullptr)
bool endFrame(const std::vector< VkSemaphore > &waitSemaphores, uint32_t currentImageIndex)
lug::Graphics::Resource::SharedPtr< lug::Graphics::Render::Texture > _fontTexture
API::GraphicsPipeline _pipeline
Vulkan::API::Buffer indexBuffer
void setQueueFamilyIndices(std::set< uint32_t > queueFamilyIndices)
const API::Queue * getQueue(const std::string &queueName) const
bool submit(const CommandBuffer &commandBuffer, const std::vector< VkSemaphore > &signalSemaphores={}, const std::vector< VkSemaphore > &waitSemaphores={}, const std::vector< VkPipelineStageFlags > &waitDstStageMasks={}, VkFence fence=VK_NULL_HANDLE) const
bool build(API::Fence &instance, VkResult *returnResult=nullptr)
void setLevel(VkCommandBufferLevel level)
const VkMemoryRequirements & getRequirements() const
Vulkan::API::DeviceMemory indexMemory
bool build(API::Buffer &instance, VkResult *returnResult=nullptr)
lug::Graphics::Vulkan::Render::Window & _window
void setSize(VkDeviceSize size)
Type type
The type of the event.
const API::Swapchain & getSwapchain() const
void setMagFilter(Render::Texture::Filter magFilter)
Mouse::Button code
The button that triggered the event.
const VkSurfaceFormatKHR & getFormat() const
API::CommandPool _transferQueueCommandPool
void * mapBuffer(const API::Buffer &buffer, VkDeviceSize size=VK_WHOLE_SIZE, VkDeviceSize offset=0) const
Vulkan::API::DeviceMemory vertexMemory
void beginRenderPass(const API::RenderPass &renderPass, const CmdBeginRenderPass ¶meters, VkSubpassContents contents=VK_SUBPASS_CONTENTS_INLINE) const
bool build(API::DescriptorSetLayout &instance, VkResult *returnResult=nullptr)
bool addLayer(const std::string &filename, bool hdr=false)
const QueueFamily * getQueueFamily() const
Vulkan::API::CommandBuffer commandBuffer
bool processEvent(const lug::Window::Event event)
const Vulkan::API::Semaphore & getSemaphore(uint32_t currentImageIndex) const
TouchScreenEvent touchScreen
bool addBuffer(API::Buffer &buffer)
static SharedPtr< T > cast(const SharedPtr< RhsT > &rhs)
Dynamic casting of a SharedPtr to another one (RhsT to T)
API::Framebuffer framebuffer
CharEvent character
A CharEvent.
const InitInfo & getInfo() const
void setMemoryFlags(VkMemoryPropertyFlags flags)
API::Device & getDevice()
bool updateBuffers(uint32_t currentImageIndex)
void setUsage(VkBufferUsageFlags usage)
const PipelineLayout * getLayout() const
std::vector< FrameData > _framesData
bool init(const std::vector< API::ImageView > &imageViews)
void setRenderPass(const API::RenderPass *renderPass)
lug::Graphics::Vulkan::Renderer & _renderer
bool initFramebuffers(const std::vector< API::ImageView > &)
void pushConstants(const CmdPushConstants ¶meters) const
wchar_t val
Raw value of the character pressed (with accents, etc.)
Resource::SharedPtr< Render::Texture > build()
Vulkan::API::Buffer vertexBuffer
std::vector< const Render::DescriptorSetPool::DescriptorSet * > texturesDescriptorSets
std::unique_ptr< Render::DescriptorSetPool::GuiTexture > _texturesDescriptorSetPool
uint16_t getHeight() const override final
uint16_t getWidth() const override final
bool begin(VkCommandBufferUsageFlags flags=VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) const
API::CommandPool _graphicQueueCommandPool
MouseEvent mouse
A MouseEvent.
API::PipelineLayout _pipelineLayout