mirror of
https://github.com/seekrs/MacroLibX.git
synced 2026-03-03 20:46:37 +00:00
fixing put pixel resize issue (#201)
This commit is contained in:
@@ -44,11 +44,16 @@ void update(void* param)
|
|||||||
mlx_set_font(mlx->mlx, "default");
|
mlx_set_font(mlx->mlx, "default");
|
||||||
mlx_string_put(mlx->mlx, mlx->win, 20, 50, (mlx_color){ .rgba = 0xFFFFFFFF }, "that's a text");
|
mlx_string_put(mlx->mlx, mlx->win, 20, 50, (mlx_color){ .rgba = 0xFFFFFFFF }, "that's a text");
|
||||||
|
|
||||||
|
int win_width;
|
||||||
|
int win_height;
|
||||||
|
|
||||||
|
mlx_get_window_size(mlx->mlx, mlx->win, &win_width, &win_height);
|
||||||
|
|
||||||
uint32_t color = 0;
|
uint32_t color = 0;
|
||||||
for(int j = 0; j < 400; j++)
|
for(int j = 0; j < win_height; j++)
|
||||||
{
|
{
|
||||||
mlx_pixel_put(mlx->mlx, mlx->win, j, j, (mlx_color){ .rgba = 0x0000FFFF + (color << 24) });
|
mlx_pixel_put(mlx->mlx, mlx->win, j, j, (mlx_color){ .rgba = 0x0000FFFF + (color << 24) });
|
||||||
mlx_pixel_put(mlx->mlx, mlx->win, 399 - j, j, (mlx_color){ .rgba = 0x0000FFFF });
|
mlx_pixel_put(mlx->mlx, mlx->win, win_width - j, j, (mlx_color){ .rgba = 0x0000FFFF });
|
||||||
color += (color < 255);
|
color += (color < 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace mlx
|
|||||||
class PutPixelManager
|
class PutPixelManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PutPixelManager(NonOwningPtr<class Renderer> renderer) : p_renderer(renderer) {}
|
PutPixelManager(NonOwningPtr<class Renderer> renderer);
|
||||||
|
|
||||||
// Returns a valid pointer when a new texture has been created
|
// Returns a valid pointer when a new texture has been created
|
||||||
NonOwningPtr<Texture> DrawPixel(int x, int y, std::uint64_t draw_layer, mlx_color color);
|
NonOwningPtr<Texture> DrawPixel(int x, int y, std::uint64_t draw_layer, mlx_color color);
|
||||||
@@ -20,6 +20,7 @@ namespace mlx
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
NonOwningPtr<Texture> GetLayer(std::uint64_t draw_layer, bool& is_newlayer);
|
NonOwningPtr<Texture> GetLayer(std::uint64_t draw_layer, bool& is_newlayer);
|
||||||
|
std::unique_ptr<Texture> NewTexture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::uint64_t, NonOwningPtr<Texture>> m_placements;
|
std::unordered_map<std::uint64_t, NonOwningPtr<Texture>> m_placements;
|
||||||
|
|||||||
@@ -89,7 +89,13 @@ namespace mlx
|
|||||||
mlx_color GetPixel(int x, int y) noexcept;
|
mlx_color GetPixel(int x, int y) noexcept;
|
||||||
void GetRegion(int x, int y, int w, int h, mlx_color* dst) noexcept;
|
void GetRegion(int x, int y, int w, int h, mlx_color* dst) noexcept;
|
||||||
void Clear(VkCommandBuffer cmd, Vec4f color) override;
|
void Clear(VkCommandBuffer cmd, Vec4f color) override;
|
||||||
|
void CopyTo(Texture& other);
|
||||||
|
void Resize(std::uint32_t width, std::uint32_t height);
|
||||||
|
|
||||||
|
void Swap(Texture& texture) noexcept;
|
||||||
|
|
||||||
|
// If a valid cmd buffer is passed, this function takes ownership and makes it invalid after
|
||||||
|
void SyncCPUBuffer(VkCommandBuffer cmd = VK_NULL_HANDLE);
|
||||||
void Update(VkCommandBuffer cmd);
|
void Update(VkCommandBuffer cmd);
|
||||||
|
|
||||||
~Texture() override { Destroy(); }
|
~Texture() override { Destroy(); }
|
||||||
|
|||||||
@@ -6,6 +6,29 @@
|
|||||||
|
|
||||||
namespace mlx
|
namespace mlx
|
||||||
{
|
{
|
||||||
|
PutPixelManager::PutPixelManager(NonOwningPtr<class Renderer> renderer) : p_renderer(renderer)
|
||||||
|
{
|
||||||
|
MLX_PROFILE_FUNCTION();
|
||||||
|
std::function<void(const EventBase&)> functor = [this](const EventBase& event)
|
||||||
|
{
|
||||||
|
// Suboptimal for multi-windows applications
|
||||||
|
if(event.What() == Event::ResizeEventCode)
|
||||||
|
{
|
||||||
|
VkExtent2D extent{ .width = 0, .height = 0 };
|
||||||
|
if(p_renderer->GetWindow())
|
||||||
|
extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain().Get());
|
||||||
|
else if(p_renderer->GetRenderTarget())
|
||||||
|
extent = VkExtent2D{ .width = p_renderer->GetRenderTarget()->GetWidth(), .height = p_renderer->GetRenderTarget()->GetHeight() };
|
||||||
|
else
|
||||||
|
FatalError("a renderer was created without window nor render target attached (wtf!?)");
|
||||||
|
|
||||||
|
for(auto& texture : m_textures)
|
||||||
|
texture->Resize(extent.width, extent.height);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EventBus::RegisterListener({ functor, "mlx_put_pixel_manager_" + std::to_string(reinterpret_cast<std::uintptr_t>(this)) });
|
||||||
|
}
|
||||||
|
|
||||||
NonOwningPtr<Texture> PutPixelManager::DrawPixel(int x, int y, std::uint64_t draw_layer, mlx_color color)
|
NonOwningPtr<Texture> PutPixelManager::DrawPixel(int x, int y, std::uint64_t draw_layer, mlx_color color)
|
||||||
{
|
{
|
||||||
MLX_PROFILE_FUNCTION();
|
MLX_PROFILE_FUNCTION();
|
||||||
@@ -53,21 +76,8 @@ namespace mlx
|
|||||||
is_newlayer = true;
|
is_newlayer = true;
|
||||||
|
|
||||||
if(m_current_texture_index >= m_textures.size())
|
if(m_current_texture_index >= m_textures.size())
|
||||||
{
|
m_textures.push_back(NewTexture());
|
||||||
VkExtent2D extent{ .width = 0, .height = 0 };
|
|
||||||
if(p_renderer->GetWindow())
|
|
||||||
extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain().Get());
|
|
||||||
else if(p_renderer->GetRenderTarget())
|
|
||||||
extent = VkExtent2D{ .width = p_renderer->GetRenderTarget()->GetWidth(), .height = p_renderer->GetRenderTarget()->GetHeight() };
|
|
||||||
else
|
|
||||||
FatalError("a renderer was created without window nor render target attached (wtf)");
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
m_textures.push_back(std::make_unique<Texture>(CPUBuffer{}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_put_pixel_layer_" + std::to_string(m_current_texture_index)));
|
|
||||||
#else
|
|
||||||
m_textures.push_back(std::make_unique<Texture>(CPUBuffer{}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, std::string_view{}));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_placements[draw_layer] = m_textures.at(m_current_texture_index).get();
|
m_placements[draw_layer] = m_textures.at(m_current_texture_index).get();
|
||||||
@@ -83,6 +93,23 @@ namespace mlx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> PutPixelManager::NewTexture()
|
||||||
|
{
|
||||||
|
VkExtent2D extent{ .width = 0, .height = 0 };
|
||||||
|
if(p_renderer->GetWindow())
|
||||||
|
extent = kvfGetSwapchainImagesSize(p_renderer->GetSwapchain().Get());
|
||||||
|
else if(p_renderer->GetRenderTarget())
|
||||||
|
extent = VkExtent2D{ .width = p_renderer->GetRenderTarget()->GetWidth(), .height = p_renderer->GetRenderTarget()->GetHeight() };
|
||||||
|
else
|
||||||
|
FatalError("a renderer was created without window nor render target attached (wtf!?)");
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
return std::make_unique<Texture>(CPUBuffer{}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_put_pixel_layer_" + std::to_string(m_current_texture_index));
|
||||||
|
#else
|
||||||
|
return std::make_unique<Texture>(CPUBuffer{}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, std::string_view{});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void PutPixelManager::ResetRenderData()
|
void PutPixelManager::ResetRenderData()
|
||||||
{
|
{
|
||||||
m_placements.clear();
|
m_placements.clear();
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
namespace mlx
|
namespace mlx
|
||||||
{
|
{
|
||||||
mlx_color ReverseColor(mlx_color color)
|
MLX_FORCEINLINE mlx_color ReverseColor(mlx_color color)
|
||||||
{
|
{
|
||||||
mlx_color reversed_color;
|
mlx_color reversed_color;
|
||||||
reversed_color.r = color.a;
|
reversed_color.r = color.a;
|
||||||
@@ -362,8 +362,16 @@ namespace mlx
|
|||||||
m_staging_buffer->Init(BufferType::Staging, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, {}, {});
|
m_staging_buffer->Init(BufferType::Staging, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, {}, {});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SyncCPUBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::SyncCPUBuffer(VkCommandBuffer cmd)
|
||||||
|
{
|
||||||
|
if(!m_staging_buffer.has_value())
|
||||||
|
return;
|
||||||
VkImageLayout old_layout = m_layout;
|
VkImageLayout old_layout = m_layout;
|
||||||
VkCommandBuffer cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
|
if(cmd == VK_NULL_HANDLE)
|
||||||
|
cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
|
||||||
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||||
TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, cmd);
|
TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, cmd);
|
||||||
kvfCopyImageToBuffer(cmd, m_staging_buffer->Get(), m_image, m_staging_buffer->GetOffset(), VK_IMAGE_ASPECT_COLOR_BIT, { m_width, m_height, 1 });
|
kvfCopyImageToBuffer(cmd, m_staging_buffer->Get(), m_image, m_staging_buffer->GetOffset(), VK_IMAGE_ASPECT_COLOR_BIT, { m_width, m_height, 1 });
|
||||||
@@ -375,6 +383,98 @@ namespace mlx
|
|||||||
kvfDestroyCommandBuffer(RenderCore::Get().GetDevice(), cmd);
|
kvfDestroyCommandBuffer(RenderCore::Get().GetDevice(), cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Texture::CopyTo(Texture& other)
|
||||||
|
{
|
||||||
|
VkImageLayout old_layout = m_layout;
|
||||||
|
VkImageLayout other_old_layout = other.GetLayout();
|
||||||
|
|
||||||
|
VkImageSubresourceLayers subresource{};
|
||||||
|
subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
subresource.mipLevel = 0;
|
||||||
|
subresource.layerCount = 1;
|
||||||
|
subresource.baseArrayLayer = 0;
|
||||||
|
|
||||||
|
VkExtent3D extent{};
|
||||||
|
extent.width = m_width;
|
||||||
|
extent.height = m_height;
|
||||||
|
extent.depth = 1;
|
||||||
|
|
||||||
|
VkOffset3D offset{};
|
||||||
|
offset.x = 0;
|
||||||
|
offset.y = 0;
|
||||||
|
offset.z = 0;
|
||||||
|
|
||||||
|
VkImageCopy region{};
|
||||||
|
region.srcSubresource = subresource;
|
||||||
|
region.dstSubresource = subresource;
|
||||||
|
region.extent = extent;
|
||||||
|
region.srcOffset = offset;
|
||||||
|
region.dstOffset = offset;
|
||||||
|
|
||||||
|
VkCommandBuffer cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
|
||||||
|
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||||
|
|
||||||
|
TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, cmd);
|
||||||
|
other.TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, cmd);
|
||||||
|
|
||||||
|
kvfCopyImageToImage(cmd, m_image, m_layout, other.Get(), other.GetLayout(), 1, ®ion);
|
||||||
|
|
||||||
|
TransitionLayout(old_layout, cmd);
|
||||||
|
other.TransitionLayout(other_old_layout, cmd);
|
||||||
|
|
||||||
|
kvfEndCommandBuffer(cmd);
|
||||||
|
|
||||||
|
SyncCPUBuffer(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Resize(std::uint32_t width, std::uint32_t height)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
Texture new_texture = Texture(CPUBuffer{}, width, height, m_format, m_is_multisampled, m_debug_name);
|
||||||
|
#else
|
||||||
|
Texture new_texture = Texture(CPUBuffer{}, width, height, m_format, m_is_multisampled, std::string_view{});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(m_staging_buffer.has_value())
|
||||||
|
new_texture.OpenCPUBuffer();
|
||||||
|
|
||||||
|
// Suboptimal operations, should bake all of them in a single command buffer
|
||||||
|
new_texture.Clear(VK_NULL_HANDLE, Vec4f{ 0.f });
|
||||||
|
CopyTo(new_texture);
|
||||||
|
|
||||||
|
Swap(new_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::Swap(Texture& texture) noexcept
|
||||||
|
{
|
||||||
|
MLX_PROFILE_FUNCTION();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::swap(m_debug_name, texture.m_debug_name);
|
||||||
|
#endif
|
||||||
|
std::swap(m_allocation, texture.m_allocation);
|
||||||
|
std::swap(m_image, texture.m_image);
|
||||||
|
std::swap(m_image_view, texture.m_image_view);
|
||||||
|
std::swap(m_sampler, texture.m_sampler);
|
||||||
|
std::swap(m_format, texture.m_format);
|
||||||
|
std::swap(m_tiling, texture.m_tiling);
|
||||||
|
std::swap(m_layout, texture.m_layout);
|
||||||
|
std::swap(m_type, texture.m_type);
|
||||||
|
std::swap(m_width, texture.m_width);
|
||||||
|
std::swap(m_height, texture.m_height);
|
||||||
|
std::swap(m_is_multisampled, texture.m_is_multisampled);
|
||||||
|
|
||||||
|
if(m_staging_buffer.has_value() && texture.m_staging_buffer.has_value())
|
||||||
|
m_staging_buffer->Swap(*texture.m_staging_buffer);
|
||||||
|
else if(m_staging_buffer.has_value())
|
||||||
|
m_staging_buffer.reset();
|
||||||
|
else if(texture.m_staging_buffer.has_value())
|
||||||
|
texture.m_staging_buffer.reset();
|
||||||
|
|
||||||
|
m_has_been_modified = true;
|
||||||
|
texture.m_has_been_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
Texture* StbTextureLoad(const std::filesystem::path& file, int* w, int* h)
|
Texture* StbTextureLoad(const std::filesystem::path& file, int* w, int* h)
|
||||||
{
|
{
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|||||||
14
third_party/kvf.h
vendored
14
third_party/kvf.h
vendored
@@ -152,6 +152,8 @@ void kvfDestroySemaphore(VkDevice device, VkSemaphore semaphore);
|
|||||||
|
|
||||||
VkImage kvfCreateImage(VkDevice device, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, KvfImageType type);
|
VkImage kvfCreateImage(VkDevice device, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, KvfImageType type);
|
||||||
void kvfCopyImageToBuffer(VkCommandBuffer cmd, VkBuffer dst, VkImage src, size_t buffer_offset, VkImageAspectFlagBits aspect, VkExtent3D extent);
|
void kvfCopyImageToBuffer(VkCommandBuffer cmd, VkBuffer dst, VkImage src, size_t buffer_offset, VkImageAspectFlagBits aspect, VkExtent3D extent);
|
||||||
|
void kvfCopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImageLayout src_layout, VkImage dst, VkImageLayout dst_layout, uint32_t count, const VkImageCopy* regions);
|
||||||
|
|
||||||
void kvfDestroyImage(VkDevice device, VkImage image);
|
void kvfDestroyImage(VkDevice device, VkImage image);
|
||||||
VkImageView kvfCreateImageView(VkDevice device, VkImage image, VkFormat format, VkImageViewType type, VkImageAspectFlags aspect, int layer_count);
|
VkImageView kvfCreateImageView(VkDevice device, VkImage image, VkFormat format, VkImageViewType type, VkImageAspectFlags aspect, int layer_count);
|
||||||
void kvfDestroyImageView(VkDevice device, VkImageView image_view);
|
void kvfDestroyImageView(VkDevice device, VkImageView image_view);
|
||||||
@@ -2147,6 +2149,18 @@ void kvfCopyImageToBuffer(VkCommandBuffer cmd, VkBuffer dst, VkImage src, size_t
|
|||||||
KVF_GET_DEVICE_FUNCTION(vkCmdCopyImageToBuffer)(cmd, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst, 1, ®ion);
|
KVF_GET_DEVICE_FUNCTION(vkCmdCopyImageToBuffer)(cmd, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst, 1, ®ion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kvfCopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImageLayout src_layout, VkImage dst, VkImageLayout dst_layout, uint32_t count, const VkImageCopy* regions)
|
||||||
|
{
|
||||||
|
KVF_ASSERT(cmd != VK_NULL_HANDLE);
|
||||||
|
KVF_ASSERT(dst != VK_NULL_HANDLE);
|
||||||
|
KVF_ASSERT(src != VK_NULL_HANDLE);
|
||||||
|
#ifdef KVF_IMPL_VK_NO_PROTOTYPES
|
||||||
|
__KvfDevice* kvf_device = __kvfGetKvfDeviceFromVkCommandBuffer(cmd);
|
||||||
|
KVF_ASSERT(kvf_device != NULL && "could not find VkDevice in registered devices");
|
||||||
|
#endif
|
||||||
|
KVF_GET_DEVICE_FUNCTION(vkCmdCopyImage)(cmd, src, src_layout, dst, dst_layout, count, regions);
|
||||||
|
}
|
||||||
|
|
||||||
void kvfDestroyImage(VkDevice device, VkImage image)
|
void kvfDestroyImage(VkDevice device, VkImage image)
|
||||||
{
|
{
|
||||||
if(image == VK_NULL_HANDLE)
|
if(image == VK_NULL_HANDLE)
|
||||||
|
|||||||
Reference in New Issue
Block a user