fixing compilation issues, working on textures

This commit is contained in:
2024-09-04 02:35:01 +02:00
parent e0da415e86
commit 8ad6d84bd2
15 changed files with 315 additions and 115 deletions

View File

@@ -19,7 +19,7 @@
Error("invalid image ptr (NULL)"); \
retval; \
} \
else if(!m_image_registry.IsTextureKnown(img)) \
else if(!m_image_registry.IsTextureKnown(static_cast<Texture*>(img))) \
{ \
Error("invalid image ptr"); \
retval; \

View File

@@ -29,7 +29,7 @@ namespace mlx
inline void LoadFont(const std::filesystem::path& filepath, float scale);
inline void TryEraseTextureFromRegistry(NonOwningPtr<Texture> texture) noexcept;
inline void TryEraseSpritesInScene(NonOwningPtr<Texture> texture) noexcept;
[[nodiscard]] MLX_FORCEINLINE bool HasWindow() const noexcept { return m_has_window; }
[[nodiscard]] MLX_FORCEINLINE Renderer& GetRenderer() { return m_renderer; }
@@ -42,6 +42,8 @@ namespace mlx
std::shared_ptr<Window> p_window;
std::unique_ptr<Scene> p_scene;
std::uint64_t m_current_depth = 0;
std::size_t m_width = 0;
std::size_t m_height = 0;

View File

@@ -7,6 +7,7 @@ namespace mlx
{
MLX_PROFILE_FUNCTION();
p_scene->ResetSprites();
m_current_depth = 0;
}
void GraphicsSupport::PixelPut(int x, int y, std::uint32_t color) noexcept
@@ -22,6 +23,15 @@ namespace mlx
void GraphicsSupport::TexturePut(NonOwningPtr<Texture> texture, int x, int y)
{
MLX_PROFILE_FUNCTION();
NonOwningPtr<Sprite> sprite = p_scene->GetSpriteFromTextureAndPosition(texture, Vec2f{ static_cast<float>(x), static_cast<float>(y) });
if(!sprite)
{
Sprite& new_sprite = p_scene->CreateSprite(texture);
new_sprite.SetPosition(Vec3f{ static_cast<float>(x), static_cast<float>(y), static_cast<float>(m_current_depth) });
}
else
sprite->SetPosition(Vec3f{ static_cast<float>(x), static_cast<float>(y), static_cast<float>(m_current_depth) });
m_current_depth++;
}
void GraphicsSupport::LoadFont(const std::filesystem::path& filepath, float scale)
@@ -29,8 +39,9 @@ namespace mlx
MLX_PROFILE_FUNCTION();
}
void GraphicsSupport::TryEraseTextureFromRegistry(NonOwningPtr<Texture> texture) noexcept
void GraphicsSupport::TryEraseSpritesInScene(NonOwningPtr<Texture> texture) noexcept
{
MLX_PROFILE_FUNCTION();
p_scene->TryEraseSpriteFromTexture(texture);
}
}

View File

@@ -17,7 +17,9 @@ namespace mlx
public:
Scene(SceneDescriptor desc);
Sprite& CreateSprite(std::shared_ptr<class Texture> texture) noexcept;
Sprite& CreateSprite(NonOwningPtr<class Texture> texture) noexcept;
NonOwningPtr<Sprite> GetSpriteFromTextureAndPosition(NonOwningPtr<Texture> texture, const Vec2f& position) const;
void TryEraseSpriteFromTexture(NonOwningPtr<Texture> texture);
inline void ResetSprites() { m_sprites.clear(); }

View File

@@ -14,7 +14,7 @@ namespace mlx
friend class Render2DPass;
public:
Sprite(std::shared_ptr<Texture> texture);
Sprite(NonOwningPtr<Texture> texture);
inline void SetColor(Vec4f color) noexcept { m_color = color; }
inline void SetPosition(Vec3f position) noexcept { m_position = position; }
@@ -22,7 +22,7 @@ namespace mlx
[[nodiscard]] inline const Vec4f& GetColor() const noexcept { return m_color; }
[[nodiscard]] inline const Vec3f& GetPosition() const noexcept { return m_position; }
[[nodiscard]] inline std::shared_ptr<Mesh> GetMesh() const { return p_mesh; }
[[nodiscard]] inline std::shared_ptr<Texture> GetTexture() const { return p_texture; }
[[nodiscard]] inline NonOwningPtr<Texture> GetTexture() const { return p_texture; }
~Sprite() = default;
@@ -43,7 +43,7 @@ namespace mlx
private:
DescriptorSet m_set;
std::shared_ptr<Texture> p_texture;
NonOwningPtr<Texture> p_texture;
std::shared_ptr<Mesh> p_mesh;
Vec4f m_color = Vec4f{ 1.0f, 1.0f, 1.0f, 1.0f };
Vec3f m_position = Vec3f{ 0.0f, 0.0f, 0.0f };

View File

@@ -47,7 +47,7 @@ namespace mlx
virtual ~Image() = default;
private:
protected:
VmaAllocation m_allocation;
VkImage m_image = VK_NULL_HANDLE;
VkImageView m_image_view = VK_NULL_HANDLE;
@@ -84,6 +84,7 @@ namespace mlx
{
Init(std::move(pixels), width, height, format, is_multisampled);
}
inline void Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, bool is_multisampled = false)
{
Image::Init(ImageType::Color, width, height, format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, is_multisampled);
@@ -91,12 +92,12 @@ namespace mlx
Image::CreateSampler();
if(pixels)
{
TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
GPUBuffer staging_buffer;
std::size_t size = width * height * kvfFormatSize(format);
staging_buffer.Init(BufferType::Staging, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, pixels);
VkCommandBuffer cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, cmd);
kvfCopyBufferToImage(cmd, Image::Get(), staging_buffer.Get(), staging_buffer.GetOffset(), VK_IMAGE_ASPECT_COLOR_BIT, { width, height, 1 });
vkEndCommandBuffer(cmd);
VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice());
@@ -104,13 +105,26 @@ namespace mlx
kvfDestroyFence(RenderCore::Get().GetDevice(), fence);
staging_buffer.Destroy();
}
if(!pixels)
TransitionLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
else
TransitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
TransitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
void SetPixel(int x, int y, std::uint32_t color) noexcept;
int GetPixel(int x, int y) noexcept;
void Update(VkCommandBuffer cmd) const;
~Texture() override { Destroy(); }
private:
void OpenCPUBuffer();
private:
std::vector<std::uint32_t> m_cpu_buffer;
std::optional<GPUBuffer> m_staging_buffer;
bool m_has_been_modified = false;
};
Texture* StbTextureLoad(const std::filesystem::path& file, int* w, int* h);
}
#endif

View File

@@ -14,7 +14,7 @@ namespace mlx
{
}, "__Application" });
m_fps.init();
m_fps.Init();
SDLManager::Get().Init();
}
@@ -26,7 +26,6 @@ namespace mlx
{
if(!m_fps.Update())
continue;
m_in.Update();
if(f_loop_hook)
f_loop_hook(p_param);
@@ -37,27 +36,15 @@ namespace mlx
gs->Render();
}
}
RenderCore::Get().GetSingleTimeCmdManager().UpdateSingleTimesCmdBuffersSubmitState();
for(auto& gs : m_graphics)
{
if(!gs)
continue;
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
gs->GetRenderer().GetCmdBuffer(i).WaitForExecution();
}
RenderCore::Get().WaitDeviceIdle();
}
void* Application::NewTexture(int w, int h)
{
MLX_PROFILE_FUNCTION();
Texture* texture = new Texture;
#ifdef DEBUG
texture->Create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM, "__mlx_unamed_user_texture");
#else
texture->Create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM, nullptr);
#endif
Texture* texture;
try { texture = new Texture({}, w, h); }
catch(...) { return NULL; }
m_image_registry.RegisterTexture(texture);
return texture;
}
@@ -66,6 +53,8 @@ namespace mlx
{
MLX_PROFILE_FUNCTION();
Texture* texture = StbTextureLoad(file, w, h);
if(texture == nullptr)
return NULL; // NULL for C compatibility
m_image_registry.RegisterTexture(texture);
return texture;
}
@@ -74,7 +63,7 @@ namespace mlx
{
MLX_PROFILE_FUNCTION();
RenderCore::Get().WaitDeviceIdle(); // TODO : synchronize with another method than waiting for GPU to be idle
if(!m_image_registry.Find(ptr))
if(!m_image_registry.IsTextureKnown(static_cast<Texture*>(ptr)))
{
Error("invalid image ptr");
return;
@@ -85,10 +74,10 @@ namespace mlx
Error("trying to destroy a texture that has already been destroyed");
else
texture->Destroy();
for(auto& gs : _graphics)
for(auto& gs : m_graphics)
{
if(gs)
gs->TryEraseTextureFromManager(texture);
gs->TryEraseSpritesInScene(texture);
}
m_image_registry.UnregisterTexture(texture);
delete texture;
@@ -96,8 +85,6 @@ namespace mlx
Application::~Application()
{
TextLibrary::Get().ClearLibrary();
FontLibrary::Get().ClearLibrary();
SDLManager::Get().Shutdown();
}
}

View File

@@ -1,7 +1,7 @@
#include <PreCompiled.h>
#include <Core/Application.h>
#include <Renderer/Core/RenderCore.h>
#include <Renderer/RenderCore.h>
#include <mlx.h>
#include <Core/Memory.h>
@@ -18,7 +18,7 @@ extern "C"
{
if(__mlx_ptr != nullptr)
{
Error("MLX cannot be initialized multiple times");
mlx::Error("MLX cannot be initialized multiple times");
return nullptr;
}
mlx::MemManager::Get(); // just to initialize the C garbage collector

View File

@@ -64,7 +64,7 @@ namespace mlx
RenderCore::Get().WaitDeviceIdle();
p_scene.reset();
m_scene_renderer.Destroy();
m_renderer->Destroy();
m_renderer.Destroy();
if(p_window)
p_window->Destroy();
}

View File

@@ -12,10 +12,31 @@ namespace mlx
m_depth.Init(m_descriptor.renderer->GetSwapchainImages().back().GetWidth(), m_descriptor.renderer->GetSwapchainImages().back().GetHeight());
}
Sprite& Scene::CreateSprite(std::shared_ptr<Texture> texture) noexcept
Sprite& Scene::CreateSprite(NonOwningPtr<Texture> texture) noexcept
{
std::shared_ptr<Sprite> sprite = std::make_shared<Sprite>(texture);
m_sprites.push_back(sprite);
return *sprite;
}
NonOwningPtr<Sprite> Scene::GetSpriteFromTextureAndPosition(NonOwningPtr<Texture> texture, const Vec2f& position) const
{
auto it = std::find_if(m_sprites.begin(), m_sprites.end(), [texture, position](const Sprite& sprite)
{
return sprite.GetPosition().x == position.x && sprite.GetPosition().y == position.y && sprite.GetTexture() == texture;
});
return (it != m_sprites.end() ? &(*it) : nullptr);
}
void Scene::TryEraseSpriteFromTexture(NonOwningPtr<Texture> texture)
{
do
{
auto it = std::find_if(m_sprites.begin(), m_sprites.end(), [texture, position](const Sprite& sprite)
{
return sprite.GetPosition().x == position.x && sprite.GetPosition().y == position.y && sprite.GetTexture() == texture;
});
m_sprites.erase(it);
} while(it != m_sprites.end());
}
}

View File

@@ -35,7 +35,7 @@ namespace mlx
return mesh;
}
Sprite::Sprite(std::shared_ptr<Texture> texture)
Sprite::Sprite(NonOwningPtr<Texture> texture)
{
Verify((bool)texture, "Sprite: invalid texture");
p_mesh = CreateQuad(0, 0, texture->GetWidth(), texture->GetHeight());

View File

@@ -4,22 +4,4 @@
namespace mlx
{
void Input::update()
{
MLX_PROFILE_FUNCTION();
_xRel = 0;
_yRel = 0;
glfwPollEvents();
static int i = 0;
i++;
if(i >= 500)
{
auto& hooks = _events_hooks[0];
auto& win_hook = hooks[MLX_WINDOW_EVENT];
if(win_hook.hook)
win_hook.hook(0, win_hook.param);
}
}
}

View File

@@ -50,7 +50,10 @@ namespace mlx
return;
bool is_single_time_cmd_buffer = (cmd == VK_NULL_HANDLE);
if(is_single_time_cmd_buffer)
{
cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
}
KvfImageType kvf_type = KVF_IMAGE_OTHER;
switch(m_type)
{
@@ -61,6 +64,13 @@ namespace mlx
}
kvfTransitionImageLayout(RenderCore::Get().GetDevice(), m_image, kvf_type, cmd, m_format, m_layout, new_layout, is_single_time_cmd_buffer);
m_layout = new_layout;
if(is_single_time_cmd_buffer)
{
vkEndCommandBuffer(cmd);
VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice());
kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence);
kvfDestroyFence(RenderCore::Get().GetDevice(), fence);
}
}
void Image::Clear(VkCommandBuffer cmd, Vec4f color)
@@ -112,4 +122,105 @@ namespace mlx
RenderCore::Get().GetAllocator().DestroyImage(m_allocation, m_image);
m_image = VK_NULL_HANDLE;
}
void Texture::SetPixel(int x, int y, std::uint32_t color) noexcept
{
MLX_PROFILE_FUNCTION();
if(x < 0 || y < 0 || static_cast<std::uint32_t>(x) > m_width || static_cast<std::uint32_t>(y) > m_height)
return;
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
m_cpu_buffer[(y * m_width) + x] = color;
m_has_been_modified = true;
}
int GetPixel(int x, int y) noexcept
{
MLX_PROFILE_FUNCTION();
if(x < 0 || y < 0 || static_cast<std::uint32_t>(x) > getWidth() || static_cast<std::uint32_t>(y) > getHeight())
return 0;
if(!m_staging_buffer.has_value())
OpenCPUBuffer();
std::uint32_t color = m_cpu_buffer[(y * m_width) + x];
std::uint8_t* bytes = reinterpret_cast<std::uint8_t*>(&color);
std::uint8_t tmp = bytes[0];
bytes[0] = bytes[2];
bytes[2] = tmp;
return *reinterpret_cast<int*>(bytes);
}
void Update(VkCommandBuffer cmd) const
{
if(!m_has_been_modified)
return;
std::memcpy(m_staging_buffer.GetMap(), m_cpu_buffer.data(), m_cpu_buffer.size() * kvfGetFormatSize(m_format));
VkImageLayout old_layout = m_layout;
VkCommandBuffer cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, cmd);
kvfCopyBufferToImage(cmd, Image::Get(), staging_buffer.Get(), staging_buffer.GetOffset(), VK_IMAGE_ASPECT_COLOR_BIT, { width, height, 1 });
TransitionLayout(old_layout, cmd);
vkEndCommandBuffer(cmd);
VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice());
kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence);
kvfDestroyFence(RenderCore::Get().GetDevice(), fence);
m_has_been_modified = false;
}
void Texture::OpenCPUBuffer()
{
MLX_PROFILE_FUNCTION();
if(m_staging_buffer.has_value())
return;
DebugLog("Texture : enabling CPU mapping");
m_staging_buffer.emplace();
std::size_t size = m_width * m_height * kvfGetFormatSize(m_format);
m_staging_buffer->Init(BufferType::Staging, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, {});
VkImageLayout old_layout = m_layout;
VkCommandBuffer cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, cmd);
kvfImageToBuffer(cmd, m_image, m_staging_buffer.Get(), m_staging_buffer.GetOffset(), VK_IMAGE_ASPECT_COLOR_BIT, { m_width, m_height, 1 });
TransitionLayout(old_layout, cmd);
vkEndCommandBuffer(cmd);
VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice());
kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence);
kvfDestroyFence(RenderCore::Get().GetDevice(), fence);
m_cpu_buffer.resize(m_width * m_height);
std::memcpy(m_cpu_buffer.data(), m_staging_buffer.GetMap(), m_cpu_buffer.size());
}
Texture* StbTextureLoad(const std::filesystem::path& file, int* w, int* h)
{
MLX_PROFILE_FUNCTION();
std::string filename = file.string();
if(!std::filesystem::exists(file))
{
Error("Image : file not found %", file);
return nullptr;
}
if(stbi_is_hdr(filename.c_str()))
{
Error("Texture : unsupported image format %", file);
return nullptr;
}
int dummy_w;
int dummy_h;
int channels;
std::uint8_t* data = stbi_load(filename.c_str(), (w == nullptr ? &dummy_w : w), (h == nullptr ? &dummy_h : h), &channels, 4);
CPUBuffer buffer((w == nullptr ? dummy_w : *w) * (h == nullptr ? dummy_h : *h) * 4);
std::memcpy(buffer.GetData(), data, buffer.GetSize());
Texture* texture;
try { texture = new Texture(buffer, (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h)); }
catch(...) { return NULL; }
stbi_image_free(data);
return texture;
}
}

View File

@@ -102,6 +102,8 @@ namespace mlx
sprite_data.color = sprite->GetColor();
if(!sprite->IsSetInit())
sprite->UpdateDescriptorSet(*p_texture_set);
Verify((bool)sprite->GetTexture(), "a sprite has no texture attached");
sprite->GetTexture()->Update(cmd);
sprite->Bind(frame_index, cmd);
std::array<VkDescriptorSet, 2> sets = { p_viewer_data_set->GetSet(frame_index), sprite->GetSet(frame_index) };
vkCmdBindDescriptorSets(cmd, m_pipeline.GetPipelineBindPoint(), m_pipeline.GetPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr);