RenderTextures and Rml Geometry
This commit is contained in:
parent
eb79ff9879
commit
68ec759c36
@ -6,6 +6,7 @@ set(LIB vulkan-renderer)
|
|||||||
|
|
||||||
find_package(Vulkan REQUIRED)
|
find_package(Vulkan REQUIRED)
|
||||||
find_package(glm CONFIG REQUIRED)
|
find_package(glm CONFIG REQUIRED)
|
||||||
|
find_package(RmlUi CONFIG REQUIRED)
|
||||||
|
|
||||||
# Link library
|
# Link library
|
||||||
|
|
||||||
@ -26,4 +27,5 @@ target_link_libraries(${LIB} PUBLIC utils)
|
|||||||
|
|
||||||
target_link_libraries(${LIB} PUBLIC p7)
|
target_link_libraries(${LIB} PUBLIC p7)
|
||||||
target_link_libraries(${LIB} PRIVATE glm::glm)
|
target_link_libraries(${LIB} PRIVATE glm::glm)
|
||||||
target_link_libraries(${LIB} PRIVATE Vulkan::Vulkan)
|
target_link_libraries(${LIB} PRIVATE Vulkan::Vulkan)
|
||||||
|
target_link_libraries(${LIB} PRIVATE RmlUi::RmlUi)
|
||||||
@ -18,7 +18,7 @@ namespace ee_vulkan {
|
|||||||
static constexpr vk::ClearValue CLEAR_DEPTH = {.depthStencil = {1.0f, 0}};
|
static constexpr vk::ClearValue CLEAR_DEPTH = {.depthStencil = {1.0f, 0}};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Mesh {
|
struct ProvinceMesh {
|
||||||
lazy<vulkan_render::Buffer<
|
lazy<vulkan_render::Buffer<
|
||||||
glm::vec2,
|
glm::vec2,
|
||||||
vk::BufferUsageFlagBits::eVertexBuffer,
|
vk::BufferUsageFlagBits::eVertexBuffer,
|
||||||
@ -76,7 +76,7 @@ export namespace ee_vulkan {
|
|||||||
|
|
||||||
lazy<vulkan_render::Texture<vulkan_render::TextureMode::DEPTH>> depth;
|
lazy<vulkan_render::Texture<vulkan_render::TextureMode::DEPTH>> depth;
|
||||||
lazy<vulkan_render::Uniform<glm::mat4>> viewProjectionUniform;
|
lazy<vulkan_render::Uniform<glm::mat4>> viewProjectionUniform;
|
||||||
Mesh provinces;
|
ProvinceMesh provinces;
|
||||||
|
|
||||||
std::size_t currentFrame = 0;
|
std::size_t currentFrame = 0;
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,15 @@ export namespace vulkan_render {
|
|||||||
RenderCommands(const Context &context, std::uint32_t maxFramesInFlight);
|
RenderCommands(const Context &context, std::uint32_t maxFramesInFlight);
|
||||||
|
|
||||||
void SubmitStagingBuffer(const BaseBuffer<BufferMode::STAGING_ACCESS> &buffer) const;
|
void SubmitStagingBuffer(const BaseBuffer<BufferMode::STAGING_ACCESS> &buffer) const;
|
||||||
|
void SubmitTexture(
|
||||||
|
const BaseBuffer<BufferMode::STATIC> &buffer,
|
||||||
|
const Texture<TextureMode::PARTIAL> &texture
|
||||||
|
) const;
|
||||||
|
void TranslateTextureLayout(
|
||||||
|
const Texture<TextureMode::PARTIAL> &texture,
|
||||||
|
const vk::ImageLayout &from,
|
||||||
|
const vk::ImageLayout &to
|
||||||
|
) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static vk::raii::CommandPool MakePool(const Context &context, std::uint32_t queueFamily);
|
static vk::raii::CommandPool MakePool(const Context &context, std::uint32_t queueFamily);
|
||||||
|
|||||||
@ -149,6 +149,7 @@ export namespace vulkan_render {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum class TextureMode {
|
enum class TextureMode {
|
||||||
|
PARTIAL,
|
||||||
RENDER,
|
RENDER,
|
||||||
DEPTH
|
DEPTH
|
||||||
};
|
};
|
||||||
@ -171,35 +172,25 @@ export namespace vulkan_render {
|
|||||||
Texture(
|
Texture(
|
||||||
const Context &context,
|
const Context &context,
|
||||||
const std::uint32_t width, const std::uint32_t height,
|
const std::uint32_t width, const std::uint32_t height,
|
||||||
const vk::Format &format,
|
const vk::Format &format
|
||||||
const std::span<std::byte> textureData
|
) requires (mode == TextureMode::PARTIAL)
|
||||||
) requires (mode == TextureMode::RENDER)
|
: context(context), width(width), height(height), format(format) {
|
||||||
: context(context), width(width), height(height), data(textureData), format(format) {
|
|
||||||
Buffer<
|
|
||||||
std::byte,
|
|
||||||
vk::BufferUsageFlagBits::eTransferSrc,
|
|
||||||
BufferMode::STATIC
|
|
||||||
> stagingBuffer(context, data);
|
|
||||||
|
|
||||||
MakeInstance(
|
MakeInstance(
|
||||||
vk::Flags(vk::ImageUsageFlagBits::eTransferDst) | vk::ImageUsageFlagBits::eSampled,
|
vk::Flags(vk::ImageUsageFlagBits::eTransferDst) | vk::ImageUsageFlagBits::eSampled,
|
||||||
vk::MemoryPropertyFlagBits::eDeviceLocal,
|
vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||||
handle,
|
handle,
|
||||||
memory
|
memory
|
||||||
);
|
);
|
||||||
|
|
||||||
/* TODO: Transition image layout
|
|
||||||
* Copy buffer to image
|
|
||||||
* Transition image layout
|
|
||||||
* Create view
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture(
|
Texture(
|
||||||
const Context &context,
|
const Context &context,
|
||||||
const Surface &surface
|
const Surface &surface
|
||||||
) requires (mode == TextureMode::DEPTH)
|
) requires (mode == TextureMode::DEPTH) :
|
||||||
: context(context), width(surface.extent.width), height(surface.extent.height), format(vk::Format::eD32SfloatS8Uint) {
|
context(context),
|
||||||
|
width(surface.extent.width),
|
||||||
|
height(surface.extent.height),
|
||||||
|
format(vk::Format::eD32SfloatS8Uint) {
|
||||||
MakeInstance(
|
MakeInstance(
|
||||||
vk::ImageUsageFlagBits::eDepthStencilAttachment,
|
vk::ImageUsageFlagBits::eDepthStencilAttachment,
|
||||||
vk::MemoryPropertyFlagBits::eDeviceLocal,
|
vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||||
@ -209,6 +200,21 @@ export namespace vulkan_render {
|
|||||||
MakeView(vk::ImageAspectFlagBits::eDepth);
|
MakeView(vk::ImageAspectFlagBits::eDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReSharper disable once CppNonExplicitConvertingConstructor
|
||||||
|
Texture(Texture<TextureMode::PARTIAL> &&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(Texture&&) noexcept = default;
|
||||||
Texture(const Texture&) = delete;
|
Texture(const Texture&) = delete;
|
||||||
Texture& operator=(const Texture&) = delete;
|
Texture& operator=(const Texture&) = delete;
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
export module vulkan_render:factory;
|
export module vulkan_render:factory;
|
||||||
import :hardware;
|
import :hardware;
|
||||||
import :resources;
|
import :resources;
|
||||||
|
import :control;
|
||||||
|
import :data;
|
||||||
|
|
||||||
export namespace vulkan_render {
|
export namespace vulkan_render {
|
||||||
|
|
||||||
@ -27,4 +29,14 @@ export namespace vulkan_render {
|
|||||||
static void SetupFrames(const Context &context, Swapchain &swapchain, const Surface &surface);
|
static void SetupFrames(const Context &context, Swapchain &swapchain, const Surface &surface);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DataFactory {
|
||||||
|
public:
|
||||||
|
static Texture<TextureMode::RENDER> CreateRenderTexture(
|
||||||
|
const Context &context,
|
||||||
|
const RenderCommands &commands,
|
||||||
|
std::uint32_t width, std::uint32_t height,
|
||||||
|
std::span<std::byte> textureData
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
89
renderers/vulkan/modules/rml/rmlui_vulkan.cppm
Normal file
89
renderers/vulkan/modules/rml/rmlui_vulkan.cppm
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* Do not include <RmlUi/Core.h> in module .cpp implementation
|
||||||
|
* to prevent MSVC internal compiler error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module;
|
||||||
|
|
||||||
|
#include <RmlUi/Core.h>
|
||||||
|
|
||||||
|
export module rmlui_vulkan;
|
||||||
|
import vulkan_render;
|
||||||
|
import utils;
|
||||||
|
import std;
|
||||||
|
|
||||||
|
namespace ee_rml {
|
||||||
|
template <typename T> using lazy = std::optional<T>;
|
||||||
|
|
||||||
|
struct GeometryMesh {
|
||||||
|
lazy<vulkan_render::Buffer<
|
||||||
|
Rml::Vertex,
|
||||||
|
vk::BufferUsageFlagBits::eVertexBuffer,
|
||||||
|
vulkan_render::BufferMode::STAGING_ACCESS
|
||||||
|
>> vertices;
|
||||||
|
lazy<vulkan_render::Buffer<
|
||||||
|
std::uint32_t,
|
||||||
|
vk::BufferUsageFlagBits::eIndexBuffer,
|
||||||
|
vulkan_render::BufferMode::STAGING_ACCESS
|
||||||
|
>> 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<const Rml::Vertex> vertices,
|
||||||
|
const Rml::Span<const std::int32_t> indices
|
||||||
|
) override {
|
||||||
|
GeometryMesh *mesh = Allocate<GeometryMesh>();
|
||||||
|
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<Rml::CompiledGeometryHandle>(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderGeometry(
|
||||||
|
Rml::CompiledGeometryHandle geometry,
|
||||||
|
Rml::Vector2f translation,
|
||||||
|
Rml::TextureHandle texture
|
||||||
|
) override {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseGeometry(const Rml::CompiledGeometryHandle geometry) override {
|
||||||
|
Deallocate(reinterpret_cast<GeometryMesh*>(geometry));
|
||||||
|
};
|
||||||
|
|
||||||
|
Rml::TextureHandle LoadTexture(Rml::Vector2i &texture_dimensions, const Rml::String &source) override {return 0;}
|
||||||
|
|
||||||
|
Rml::TextureHandle GenerateTexture(
|
||||||
|
Rml::Span<const std::uint8_t> 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@ -74,6 +74,83 @@ void vulkan_render::RenderCommands::SubmitStagingBuffer(const BaseBuffer<BufferM
|
|||||||
cmd.Submit(buffer.context.device.transfer);
|
cmd.Submit(buffer.context.device.transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vulkan_render::RenderCommands::SubmitTexture(
|
||||||
|
const BaseBuffer<BufferMode::STATIC> &buffer,
|
||||||
|
const Texture<TextureMode::PARTIAL> &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<TextureMode::PARTIAL> &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) {
|
vk::raii::CommandPool vulkan_render::RenderCommands::MakePool(const Context &context, const std::uint32_t queueFamily) {
|
||||||
return context.device.handle.createCommandPool({
|
return context.device.handle.createCommandPool({
|
||||||
.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
|
.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
|
||||||
|
|||||||
@ -85,3 +85,33 @@ void vulkan_render::ResourcesFactory::SetupFrames(const Context &context, Swapch
|
|||||||
}
|
}
|
||||||
LOG(INFO, "Frame views are ready.");
|
LOG(INFO, "Frame views are ready.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vulkan_render::Texture<vulkan_render::TextureMode::RENDER> vulkan_render::DataFactory::CreateRenderTexture(
|
||||||
|
const Context &context,
|
||||||
|
const RenderCommands &commands,
|
||||||
|
const std::uint32_t width, const std::uint32_t height,
|
||||||
|
const std::span<std::byte> textureData
|
||||||
|
) {
|
||||||
|
Texture<TextureMode::PARTIAL> 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);
|
||||||
|
}
|
||||||
|
|||||||
6
renderers/vulkan/src/rml/rmlui_vulkan.cpp
Normal file
6
renderers/vulkan/src/rml/rmlui_vulkan.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// module;
|
||||||
|
//
|
||||||
|
// #include <RmlUi/Core.h>
|
||||||
|
//
|
||||||
|
// module rmlui_vulkan;
|
||||||
|
//
|
||||||
Loading…
x
Reference in New Issue
Block a user