diff --git a/implementations/Crafter.Graphics-Window.cpp b/implementations/Crafter.Graphics-Window.cpp index 7b399bd..fad11c8 100644 --- a/implementations/Crafter.Graphics-Window.cpp +++ b/implementations/Crafter.Graphics-Window.cpp @@ -619,7 +619,7 @@ void Window::UpdateCursorImage() { void Window::StartSync() { #ifdef CRAFTER_GRAPHICS_WINDOW_WAYLAND while (open && wl_display_dispatch(Device::display) != -1) { - + onBeforeUpdate.Invoke(); } #endif #ifdef CRAFTER_GRAPHICS_WINDOW_WIN32 @@ -629,6 +629,7 @@ void Window::StartSync() { TranslateMessage(&msg); DispatchMessage(&msg); } + onBeforeUpdate.Invoke(); if(updating) { Update(); } @@ -997,6 +998,31 @@ void Window::FinishInit() { Device::CheckVkResult(vkQueueWaitIdle(Device::queue)); } +VkCommandBuffer Window::GetCmd() { + VkCommandBufferBeginInfo cmdBufInfo {}; + cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + Device::CheckVkResult(vkBeginCommandBuffer(drawCmdBuffers[currentBuffer], &cmdBufInfo)); + + VkImageSubresourceRange range{}; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.baseMipLevel = 0; + range.levelCount = VK_REMAINING_MIP_LEVELS; + range.baseArrayLayer = 0; + range.layerCount = VK_REMAINING_ARRAY_LAYERS; + + return drawCmdBuffers[currentBuffer]; +} + +void Window::EndCmd(VkCommandBuffer cmd) { + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; + Device::CheckVkResult(vkEndCommandBuffer(drawCmdBuffers[currentBuffer])); + Device::CheckVkResult(vkQueueSubmit(Device::queue, 1, &submitInfo, VK_NULL_HANDLE)); + Device::CheckVkResult(vkQueueWaitIdle(Device::queue)); +} + #endif #ifdef CRAFTER_GRAPHICS_WINDOW_WAYLAND diff --git a/interfaces/Crafter.Graphics-DescriptorPoolVulkan.cppm b/interfaces/Crafter.Graphics-DescriptorPoolVulkan.cppm index 7cee35a..4ed941d 100644 --- a/interfaces/Crafter.Graphics-DescriptorPoolVulkan.cppm +++ b/interfaces/Crafter.Graphics-DescriptorPoolVulkan.cppm @@ -153,11 +153,15 @@ export namespace Crafter { } public: + ~DescriptorPool() { + vkDestroyDescriptorPool(Device::device, descriptorPool, nullptr); + } void BuildPool(std::span poolSizes, std::span setLayouts) { if(descriptorPool != VK_NULL_HANDLE) { vkDestroyDescriptorPool(Device::device, descriptorPool, nullptr); } + sets.resize(setLayouts.size()); VkDescriptorPoolCreateInfo descriptorPoolInfo { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, diff --git a/interfaces/Crafter.Graphics-RenderingElement2D.cppm b/interfaces/Crafter.Graphics-RenderingElement2D.cppm index 233242f..1dc448d 100644 --- a/interfaces/Crafter.Graphics-RenderingElement2D.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement2D.cppm @@ -153,7 +153,7 @@ export namespace Crafter { } } - std::vector ResizeText(RendertargetBase& window, Transform2D& parent, const std::string_view text, float& size, Font& font, std::uint8_t frame, TextOverflowMode overflowMode = TextOverflowMode::Clip, TextScaleMode scaleMode = TextScaleMode::None) { + std::vector ResizeText(RendertargetBase& window, Transform2D& parent, const std::string_view text, float& size, Font& font, TextOverflowMode overflowMode = TextOverflowMode::Clip, TextScaleMode scaleMode = TextScaleMode::None) { float scale = stbtt_ScaleForPixelHeight(&font.font, size); int baseline = (int)(font.ascent * scale); @@ -293,7 +293,7 @@ export namespace Crafter { return lines; } - void RenderText(std::span lines, float size, Vector color, Font& font, std::uint8_t frame, TextAlignment alignment = TextAlignment::Left, std::uint32_t offsetX = 0, std::uint32_t offsetY = 0, OpaqueType opaque = OpaqueType::FullyOpaque) { + void RenderText(std::span lines, float size, Vector color, Font& font, TextAlignment alignment = TextAlignment::Left, std::uint32_t offsetX = 0, std::uint32_t offsetY = 0, OpaqueType opaque = OpaqueType::FullyOpaque) { float scale = stbtt_ScaleForPixelHeight(&font.font, size); int baseline = (int)(font.ascent * scale); std::uint32_t lineHeight = (font.ascent - font.descent) * scale; diff --git a/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm b/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm index e42af39..df29672 100644 --- a/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm @@ -97,16 +97,22 @@ export namespace Crafter { template struct RenderingElement2DBase : Transform2D { ScaleData2D oldScale[Frames]; + bool redraw[Frames]; std::vector> buffer; OpaqueType opaque; RenderingElement2DBase(Anchor2D anchor) : Transform2D(anchor) { for(std::uint8_t i = 0; i < Frames; i++) { - this->scaled[i].size.x = 0; + this->scaled.size.x = 0; } } RenderingElement2DBase(Anchor2D anchor, OpaqueType opaque) : Transform2D(anchor), opaque(opaque) { for(std::uint8_t i = 0; i < Frames; i++) { - this->scaled[i].size.x = 0; + this->scaled.size.x = 0; + } + } + void Redraw() { + for(std::uint8_t i = 0; i < Frames; i++) { + redraw[i] = true; } } }; diff --git a/interfaces/Crafter.Graphics-Rendertarget.cppm b/interfaces/Crafter.Graphics-Rendertarget.cppm index a3ec6ae..5fc70c2 100644 --- a/interfaces/Crafter.Graphics-Rendertarget.cppm +++ b/interfaces/Crafter.Graphics-Rendertarget.cppm @@ -33,8 +33,6 @@ export namespace Crafter { Transform2D transform; std::int32_t sizeX; std::int32_t sizeY; - std::vector elements; - std::vector dirtyRects[Frames]; RendertargetBase() = default; RendertargetBase(std::int16_t sizeX, std::int16_t sizeY) : sizeX(sizeX), sizeY(sizeY), transform({0, 0, 1, 1, 0, 0, 0}){ transform.scaled.size.x = sizeX; @@ -42,11 +40,6 @@ export namespace Crafter { transform.scaled.position.x = 0; transform.scaled.position.y = 0; } - void AddDirtyRect(ScaleData2D scale) { - for(std::uint8_t i = 0; i < Frames; i++) { - dirtyRects[i].emplace_back(std::max(scale.position.x, std::int32_t(0)), std::min(scale.position.x + scale.size.x, sizeX), std::max(scale.position.y, std::int32_t(0)), std::min(scale.position.y + scale.size.y, sizeY)); - } - } }; template @@ -56,7 +49,7 @@ export namespace Crafter { Rendertarget(std::int16_t sizeX, std::int16_t sizeY) : RendertargetBase(sizeX, sizeY) { } - void RenderElement(Transform2D* elementTransform, std::uint8_t frame) { + void RenderElement(Transform2D* elementTransform, std::uint8_t frame, std::vector&& dirtyRects) { RenderingElement2DBase* element = dynamic_cast*>(elementTransform); if(element) { #ifdef CRAFTER_TIMING @@ -67,7 +60,7 @@ export namespace Crafter { return; } - for(ClipRect dirty : this->dirtyRects[frame]) { + for(ClipRect dirty : dirtyRects) { dirty.left = std::max(element->scaled.position.x, dirty.left); dirty.top = std::max(element->scaled.position.y, dirty.top); dirty.right = std::min(element->scaled.position.x+element->scaled.size.x, dirty.right); @@ -142,11 +135,31 @@ export namespace Crafter { } std::sort(elementTransform->children.begin(), elementTransform->children.end(), [](Transform2D* a, Transform2D* b){ return a->anchor.z < b->anchor.z; }); for(Transform2D* child : elementTransform->children) { - this->RenderElement(child, frame); + this->RenderElement(child, frame, std::move(dirtyRects)); } } - void Render(std::uint8_t frame) { - std::sort(this->elements.begin(), this->elements.end(), [](Transform2D* a, Transform2D* b){ return a->anchor.z < b->anchor.z; }); + + void AddOldRects(Transform2D* elementTransform, std::uint8_t frame, std::vector& clipRects) { + RenderingElement2DBase* element = dynamic_cast*>(elementTransform); + if(element) { + if(element->scaled.position.x != element->oldScale[frame].position.x || element->scaled.position.y != element->oldScale[frame].position.y || element->scaled.size.x != element->oldScale[frame].size.x || element->scaled.size.y != element->oldScale[frame].size.y || element->redraw[frame]) { + clipRects.emplace_back(std::max(element->scaled.position.x, std::int32_t(0)), std::min(element->scaled.position.x + element->scaled.size.x, this->sizeX), std::max(element->scaled.position.y, std::int32_t(0)), std::min(element->scaled.position.y + element->scaled.size.y, this->sizeY)); + clipRects.emplace_back(std::max(element->oldScale[frame].position.x, std::int32_t(0)), std::min(element->oldScale[frame].position.x + element->oldScale[frame].size.x, this->sizeX), std::max(element->oldScale[frame].position.y, std::int32_t(0)), std::min(element->oldScale[frame].position.y + element->oldScale[frame].size.y, this->sizeY)); + element->oldScale[frame] = element->scaled; + element->redraw[frame] = false; + } + } + for(Transform2D* child : elementTransform->children) { + AddOldRects(child, frame, clipRects); + } + } + + bool Render(std::uint8_t frame) { + std::sort(this->transform.children.begin(), this->transform.children.end(), [](Transform2D* a, Transform2D* b){ return a->anchor.z < b->anchor.z; }); + std::vector clipRects; + for(Transform2D* child : this->transform.children) { + AddOldRects(child, frame, clipRects); + } //std::vector newClip; // for (std::uint32_t i = 0; i < dirtyRects.size(); i++) { @@ -247,8 +260,8 @@ export namespace Crafter { // ++rectIndex; // } - if (!this->dirtyRects[frame].empty()) { - for (ClipRect rect : this->dirtyRects[frame]) { + if (!clipRects.empty()) { + for (ClipRect rect : clipRects) { for (std::int32_t y = rect.top; y < rect.bottom; y++) { for (std::int32_t x = rect.left; x < rect.right; x++) { this->buffer[frame][y * this->sizeX + x] = {0, 0, 0, 0}; @@ -256,10 +269,12 @@ export namespace Crafter { } } - for(Transform2D* child : this->elements) { - RenderElement(child, frame); + for(Transform2D* child : this->transform.children) { + RenderElement(child, frame, std::move(clipRects)); } - this->dirtyRects[frame].clear(); + return true; + } else { + return false; } } }; diff --git a/interfaces/Crafter.Graphics-Window.cppm b/interfaces/Crafter.Graphics-Window.cppm index 76365dd..ba07108 100644 --- a/interfaces/Crafter.Graphics-Window.cppm +++ b/interfaces/Crafter.Graphics-Window.cppm @@ -69,6 +69,7 @@ export namespace Crafter { std::uint32_t height; std::chrono::time_point lastFrameBegin; Event onClose; + Event onBeforeUpdate; Event onUpdate; bool open = true; bool updating = false; @@ -180,6 +181,8 @@ export namespace Crafter { void SetPipelineRT(PipelineRTVulkan& pipeline); VkCommandBuffer StartInit(); void FinishInit(); + VkCommandBuffer GetCmd(); + void EndCmd(VkCommandBuffer cmd); void CreateSwapchain(); static constexpr std::uint8_t numFrames = 3; VkSurfaceKHR vulkanSurface = VK_NULL_HANDLE;