diff --git a/renderers/vulkan/CMakeLists.txt b/renderers/vulkan/CMakeLists.txt index 2d868ba..f26cfb4 100644 --- a/renderers/vulkan/CMakeLists.txt +++ b/renderers/vulkan/CMakeLists.txt @@ -6,6 +6,7 @@ set(LIB vulkan-renderer) find_package(Vulkan REQUIRED) find_package(glm CONFIG REQUIRED) +find_package(RmlUi CONFIG REQUIRED) # Link library @@ -26,4 +27,5 @@ target_link_libraries(${LIB} PUBLIC utils) target_link_libraries(${LIB} PUBLIC p7) target_link_libraries(${LIB} PRIVATE glm::glm) -target_link_libraries(${LIB} PRIVATE Vulkan::Vulkan) \ No newline at end of file +target_link_libraries(${LIB} PRIVATE Vulkan::Vulkan) +target_link_libraries(${LIB} PRIVATE RmlUi::RmlUi) \ No newline at end of file diff --git a/renderers/vulkan/modules/VulkanRenderer.cppm b/renderers/vulkan/modules/VulkanRenderer.cppm index 61d23fa..fe33853 100644 --- a/renderers/vulkan/modules/VulkanRenderer.cppm +++ b/renderers/vulkan/modules/VulkanRenderer.cppm @@ -18,7 +18,7 @@ namespace ee_vulkan { static constexpr vk::ClearValue CLEAR_DEPTH = {.depthStencil = {1.0f, 0}}; }; - struct Mesh { + struct ProvinceMesh { lazy> depth; lazy> viewProjectionUniform; - Mesh provinces; + ProvinceMesh provinces; std::size_t currentFrame = 0; diff --git a/renderers/vulkan/modules/control.cppm b/renderers/vulkan/modules/control.cppm index 57c6236..393d14b 100644 --- a/renderers/vulkan/modules/control.cppm +++ b/renderers/vulkan/modules/control.cppm @@ -47,6 +47,15 @@ export namespace vulkan_render { RenderCommands(const Context &context, std::uint32_t maxFramesInFlight); void SubmitStagingBuffer(const BaseBuffer &buffer) const; + void SubmitTexture( + const BaseBuffer &buffer, + const Texture &texture + ) const; + void TranslateTextureLayout( + const Texture &texture, + const vk::ImageLayout &from, + const vk::ImageLayout &to + ) const; private: static vk::raii::CommandPool MakePool(const Context &context, std::uint32_t queueFamily); diff --git a/renderers/vulkan/modules/data.cppm b/renderers/vulkan/modules/data.cppm index 71cd310..8a3acc4 100644 --- a/renderers/vulkan/modules/data.cppm +++ b/renderers/vulkan/modules/data.cppm @@ -149,6 +149,7 @@ export namespace vulkan_render { }; enum class TextureMode { + PARTIAL, RENDER, DEPTH }; @@ -171,35 +172,25 @@ export namespace vulkan_render { Texture( const Context &context, const std::uint32_t width, const std::uint32_t height, - const vk::Format &format, - const std::span textureData - ) requires (mode == TextureMode::RENDER) - : context(context), width(width), height(height), data(textureData), format(format) { - Buffer< - std::byte, - vk::BufferUsageFlagBits::eTransferSrc, - BufferMode::STATIC - > stagingBuffer(context, data); - + const vk::Format &format + ) requires (mode == TextureMode::PARTIAL) + : context(context), width(width), height(height), format(format) { MakeInstance( vk::Flags(vk::ImageUsageFlagBits::eTransferDst) | vk::ImageUsageFlagBits::eSampled, vk::MemoryPropertyFlagBits::eDeviceLocal, handle, memory ); - - /* TODO: Transition image layout - * Copy buffer to image - * Transition image layout - * Create view - */ } Texture( const Context &context, const Surface &surface - ) requires (mode == TextureMode::DEPTH) - : context(context), width(surface.extent.width), height(surface.extent.height), format(vk::Format::eD32SfloatS8Uint) { + ) requires (mode == TextureMode::DEPTH) : + context(context), + width(surface.extent.width), + height(surface.extent.height), + format(vk::Format::eD32SfloatS8Uint) { MakeInstance( vk::ImageUsageFlagBits::eDepthStencilAttachment, vk::MemoryPropertyFlagBits::eDeviceLocal, @@ -209,6 +200,21 @@ export namespace vulkan_render { MakeView(vk::ImageAspectFlagBits::eDepth); } + // ReSharper disable once CppNonExplicitConvertingConstructor + Texture(Texture &&from) requires (mode == TextureMode::RENDER) : + context(from.context), + width(from.width), + height(from.height), + format(from.format) { + if (*from.view == nullptr) { + LOG(ERROR, "Corrupted render texture created, source data is not complete."); + } + } + + void Init(const vk::ImageAspectFlags &flags) requires (mode == TextureMode::PARTIAL) { + MakeView(flags); + } + Texture(Texture&&) noexcept = default; Texture(const Texture&) = delete; Texture& operator=(const Texture&) = delete; diff --git a/renderers/vulkan/modules/factory.cppm b/renderers/vulkan/modules/factory.cppm index a578a13..424eee8 100644 --- a/renderers/vulkan/modules/factory.cppm +++ b/renderers/vulkan/modules/factory.cppm @@ -5,6 +5,8 @@ export module vulkan_render:factory; import :hardware; import :resources; +import :control; +import :data; export namespace vulkan_render { @@ -27,4 +29,14 @@ export namespace vulkan_render { static void SetupFrames(const Context &context, Swapchain &swapchain, const Surface &surface); }; + class DataFactory { + public: + static Texture CreateRenderTexture( + const Context &context, + const RenderCommands &commands, + std::uint32_t width, std::uint32_t height, + std::span textureData + ); + }; + } \ No newline at end of file diff --git a/renderers/vulkan/modules/rml/rmlui_vulkan.cppm b/renderers/vulkan/modules/rml/rmlui_vulkan.cppm new file mode 100644 index 0000000..389b4d0 --- /dev/null +++ b/renderers/vulkan/modules/rml/rmlui_vulkan.cppm @@ -0,0 +1,89 @@ +/** + * Do not include in module .cpp implementation + * to prevent MSVC internal compiler error + */ + +module; + +#include + +export module rmlui_vulkan; +import vulkan_render; +import utils; +import std; + +namespace ee_rml { + template using lazy = std::optional; + + struct GeometryMesh { + lazy> vertices; + lazy> indices; + }; +} + +export namespace ee_rml { + + struct RenderContext { + vulkan_render::Context &context; + vulkan_render::RenderCommands &commands; + }; + + class RmlVulkan final : public Rml::RenderInterface { + public: + explicit RmlVulkan(RenderContext &renderContext) : renderer(renderContext) {} + + Rml::CompiledGeometryHandle CompileGeometry( + const Rml::Span vertices, + const Rml::Span indices + ) override { + GeometryMesh *mesh = Allocate(); + mesh->vertices.emplace(renderer.context, vertices.size()); + mesh->indices.emplace(renderer.context, indices.size()); + + std::ranges::copy(vertices, mesh->vertices->content.data()); + std::ranges::copy(indices, mesh->indices->content.data()); + + renderer.commands.SubmitStagingBuffer(*mesh->vertices); + renderer.commands.SubmitStagingBuffer(*mesh->indices); + + return reinterpret_cast(mesh); + } + + void RenderGeometry( + Rml::CompiledGeometryHandle geometry, + Rml::Vector2f translation, + Rml::TextureHandle texture + ) override { + + } + + void ReleaseGeometry(const Rml::CompiledGeometryHandle geometry) override { + Deallocate(reinterpret_cast(geometry)); + }; + + Rml::TextureHandle LoadTexture(Rml::Vector2i &texture_dimensions, const Rml::String &source) override {return 0;} + + Rml::TextureHandle GenerateTexture( + Rml::Span source, + Rml::Vector2i source_dimensions + ) override {return 0;} + + void ReleaseTexture(Rml::TextureHandle texture) override {} + + void EnableScissorRegion(bool enable) override {} + + void SetScissorRegion(Rml::Rectanglei region) override {} + + private: + RenderContext &renderer; + }; + +} \ No newline at end of file diff --git a/renderers/vulkan/src/control.cpp b/renderers/vulkan/src/control.cpp index 0772f50..0cb9d51 100644 --- a/renderers/vulkan/src/control.cpp +++ b/renderers/vulkan/src/control.cpp @@ -74,6 +74,83 @@ void vulkan_render::RenderCommands::SubmitStagingBuffer(const BaseBuffer &buffer, + const Texture &texture +) const { + const Command cmd(buffer.context, graphicsPool); + + const vk::BufferImageCopy copyRegion { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1 + }, + .imageOffset = {0, 0, 0}, + .imageExtent = {texture.width, texture.height, 1} + }; + + cmd.handle.copyBufferToImage(buffer.handle, texture.handle, vk::ImageLayout::eTransferDstOptimal, {copyRegion}); + + cmd.Submit(buffer.context.device.graphics); +} + +void vulkan_render::RenderCommands::TranslateTextureLayout( + const Texture &texture, + const vk::ImageLayout &from, + const vk::ImageLayout &to +) const { + const Command cmd(texture.context, graphicsPool); + + vk::ImageMemoryBarrier barrier { + .oldLayout = from, + .newLayout = to, + .srcQueueFamilyIndex = vk::QueueFamilyIgnored, + .dstQueueFamilyIndex = vk::QueueFamilyIgnored, + .image = texture.handle, + .subresourceRange = { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1 + }, + }; + + vk::PipelineStageFlags sourceStage; + vk::PipelineStageFlags destinationStage; + + if (from == vk::ImageLayout::eUndefined && to == vk::ImageLayout::eTransferDstOptimal) { + barrier.srcAccessMask = vk::AccessFlagBits::eNone; + barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite; + + sourceStage = vk::PipelineStageFlagBits::eTopOfPipe; + destinationStage = vk::PipelineStageFlagBits::eTransfer; + } else if (from == vk::ImageLayout::eTransferDstOptimal && to == vk::ImageLayout::eReadOnlyOptimal) { + barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; + barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; + + sourceStage = vk::PipelineStageFlagBits::eTransfer; + destinationStage = vk::PipelineStageFlagBits::eFragmentShader; + } else { + LOG(ERROR, "Unsupported layout transition: %d -> %d.", from, to); + } + + cmd.handle.pipelineBarrier( + sourceStage, destinationStage, + vk::DependencyFlags(0), + nullptr, + nullptr, + {barrier} + ); + + cmd.Submit(texture.context.device.graphics); +} + vk::raii::CommandPool vulkan_render::RenderCommands::MakePool(const Context &context, const std::uint32_t queueFamily) { return context.device.handle.createCommandPool({ .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer, diff --git a/renderers/vulkan/src/factory.cpp b/renderers/vulkan/src/factory.cpp index 96c5077..deec7f7 100644 --- a/renderers/vulkan/src/factory.cpp +++ b/renderers/vulkan/src/factory.cpp @@ -85,3 +85,33 @@ void vulkan_render::ResourcesFactory::SetupFrames(const Context &context, Swapch } LOG(INFO, "Frame views are ready."); } + +vulkan_render::Texture vulkan_render::DataFactory::CreateRenderTexture( + const Context &context, + const RenderCommands &commands, + const std::uint32_t width, const std::uint32_t height, + const std::span textureData +) { + Texture texture(context, width, height, vk::Format::eR8G8B8A8Srgb); + const Buffer< + std::byte, + vk::BufferUsageFlagBits::eTransferSrc, + BufferMode::STATIC + > stagingBuffer(context, textureData); + + commands.TranslateTextureLayout( + texture, + vk::ImageLayout::eUndefined, + vk::ImageLayout::eTransferDstOptimal + ); + commands.SubmitTexture(stagingBuffer, texture); + commands.TranslateTextureLayout( + texture, + vk::ImageLayout::eTransferDstOptimal, + vk::ImageLayout::eShaderReadOnlyOptimal + ); + + texture.Init(vk::ImageAspectFlagBits::eColor); + + return std::move(texture); +} diff --git a/renderers/vulkan/src/rml/rmlui_vulkan.cpp b/renderers/vulkan/src/rml/rmlui_vulkan.cpp new file mode 100644 index 0000000..775ce37 --- /dev/null +++ b/renderers/vulkan/src/rml/rmlui_vulkan.cpp @@ -0,0 +1,6 @@ +// module; +// +// #include +// +// module rmlui_vulkan; +//