mirror of
https://github.com/seekrs/MacroLibX.git
synced 2026-01-12 07:03:34 +00:00
adding debug vulkan resources names
This commit is contained in:
@@ -4,8 +4,9 @@
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
void GPUBuffer::Init(BufferType type, VkDeviceSize size, VkBufferUsageFlags usage, CPUBuffer data)
|
||||
void GPUBuffer::Init(BufferType type, VkDeviceSize size, VkBufferUsageFlags usage, CPUBuffer data, std::string_view debug_name)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
VmaAllocationCreateInfo alloc_info{};
|
||||
alloc_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
||||
alloc_info.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
@@ -24,10 +25,7 @@ namespace mlx
|
||||
else // LowDynamic or Staging
|
||||
m_usage = usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
if(type == BufferType::Staging && data.Empty())
|
||||
Warning("Vulkan : trying to create staging buffer without data (wtf?)");
|
||||
|
||||
CreateBuffer(size, m_usage, alloc_info);
|
||||
CreateBuffer(size, m_usage, alloc_info, std::move(debug_name));
|
||||
|
||||
if(!data.Empty())
|
||||
{
|
||||
@@ -38,21 +36,38 @@ namespace mlx
|
||||
PushToGPU();
|
||||
}
|
||||
|
||||
void GPUBuffer::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaAllocationCreateInfo alloc_info)
|
||||
void GPUBuffer::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaAllocationCreateInfo alloc_info, std::string_view debug_name)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
VkBufferCreateInfo bufferInfo{};
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.size = size;
|
||||
bufferInfo.usage = usage;
|
||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
m_allocation = RenderCore::Get().GetAllocator().CreateBuffer(&bufferInfo, &alloc_info, m_buffer, nullptr);
|
||||
#ifdef DEBUG
|
||||
std::string alloc_name{ debug_name };
|
||||
if(usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
|
||||
alloc_name.append("_index_buffer");
|
||||
else if(usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||
alloc_name.append("_vertex_buffer");
|
||||
else if(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
||||
alloc_name.append("_uniform_buffer");
|
||||
else
|
||||
alloc_name.append("_buffer");
|
||||
m_allocation = RenderCore::Get().GetAllocator().CreateBuffer(&bufferInfo, &alloc_info, m_buffer, alloc_name.c_str());
|
||||
m_debug_name = std::move(alloc_name);
|
||||
#else
|
||||
m_allocation = RenderCore::Get().GetAllocator().CreateBuffer(&bufferInfo, &alloc_info, m_buffer, nullptr);
|
||||
#endif
|
||||
if(alloc_info.flags != 0)
|
||||
RenderCore::Get().GetAllocator().MapMemory(m_allocation, &p_map);
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
bool GPUBuffer::CopyFrom(const GPUBuffer& buffer) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(!(m_usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT))
|
||||
{
|
||||
Error("Vulkan : buffer cannot be the destination of a copy because it does not have the correct usage flag");
|
||||
@@ -77,12 +92,19 @@ namespace mlx
|
||||
|
||||
void GPUBuffer::PushToGPU() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
VmaAllocationCreateInfo alloc_info{};
|
||||
alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||
|
||||
GPUBuffer new_buffer;
|
||||
new_buffer.m_usage = (this->m_usage & 0xFFFFFFFC) | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
new_buffer.CreateBuffer(m_size, new_buffer.m_usage, alloc_info);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::string new_name = m_debug_name + "_gpu";
|
||||
new_buffer.CreateBuffer(m_size, new_buffer.m_usage, alloc_info, new_name);
|
||||
#else
|
||||
new_buffer.CreateBuffer(m_size, new_buffer.m_usage, alloc_info, {});
|
||||
#endif
|
||||
|
||||
if(new_buffer.CopyFrom(*this))
|
||||
Swap(new_buffer);
|
||||
@@ -92,15 +114,21 @@ namespace mlx
|
||||
|
||||
void GPUBuffer::Destroy() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_buffer == VK_NULL_HANDLE)
|
||||
return;
|
||||
RenderCore::Get().GetAllocator().UnmapMemory(m_allocation);
|
||||
RenderCore::Get().GetAllocator().DestroyBuffer(m_allocation, m_buffer);
|
||||
#ifdef DEBUG
|
||||
RenderCore::Get().GetAllocator().DestroyBuffer(m_allocation, m_buffer, m_debug_name.c_str());
|
||||
#else
|
||||
RenderCore::Get().GetAllocator().DestroyBuffer(m_allocation, m_buffer, nullptr);
|
||||
#endif
|
||||
m_buffer = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void GPUBuffer::Swap(GPUBuffer& buffer) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
std::swap(m_buffer, buffer.m_buffer);
|
||||
std::swap(m_allocation, buffer.m_allocation);
|
||||
std::swap(m_size, buffer.m_size);
|
||||
@@ -111,6 +139,7 @@ namespace mlx
|
||||
|
||||
void VertexBuffer::SetData(CPUBuffer data)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(data.GetSize() > m_size)
|
||||
{
|
||||
Error("Vulkan : trying to store to much data in a vertex buffer (% bytes in % bytes)", data.GetSize(), m_size);
|
||||
@@ -122,13 +151,18 @@ namespace mlx
|
||||
return;
|
||||
}
|
||||
GPUBuffer staging;
|
||||
staging.Init(BufferType::Staging, data.GetSize(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, data);
|
||||
#ifdef DEBUG
|
||||
staging.Init(BufferType::Staging, data.GetSize(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, data, m_debug_name);
|
||||
#else
|
||||
staging.Init(BufferType::Staging, data.GetSize(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, data, {});
|
||||
#endif
|
||||
CopyFrom(staging);
|
||||
staging.Destroy();
|
||||
}
|
||||
|
||||
void IndexBuffer::SetData(CPUBuffer data)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(data.GetSize() > m_size)
|
||||
{
|
||||
Error("Vulkan : trying to store to much data in an index buffer (% bytes in % bytes)", data.GetSize(), m_size);
|
||||
@@ -140,16 +174,25 @@ namespace mlx
|
||||
return;
|
||||
}
|
||||
GPUBuffer staging;
|
||||
staging.Init(BufferType::Staging, data.GetSize(), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, data);
|
||||
#ifdef DEBUG
|
||||
staging.Init(BufferType::Staging, data.GetSize(), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, data, m_debug_name);
|
||||
#else
|
||||
staging.Init(BufferType::Staging, data.GetSize(), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, data, {});
|
||||
#endif
|
||||
CopyFrom(staging);
|
||||
staging.Destroy();
|
||||
}
|
||||
|
||||
void UniformBuffer::Init(std::uint32_t size)
|
||||
void UniformBuffer::Init(std::uint32_t size, std::string_view debug_name)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
m_buffers[i].Init(BufferType::HighDynamic, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, {});
|
||||
#ifdef DEBUG
|
||||
m_buffers[i].Init(BufferType::HighDynamic, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, {}, std::string{ debug_name } + '_' + std::to_string(i));
|
||||
#else
|
||||
m_buffers[i].Init(BufferType::HighDynamic, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, {}, {});
|
||||
#endif
|
||||
m_maps[i] = m_buffers[i].GetMap();
|
||||
if(m_maps[i] == nullptr)
|
||||
FatalError("Vulkan : unable to map a uniform buffer");
|
||||
@@ -158,6 +201,7 @@ namespace mlx
|
||||
|
||||
void UniformBuffer::SetData(CPUBuffer data, std::size_t frame_index)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(data.GetSize() != m_buffers[frame_index].GetSize())
|
||||
{
|
||||
Error("Vulkan : invalid data size to update to a uniform buffer, % != %", data.GetSize(), m_buffers[frame_index].GetSize());
|
||||
@@ -169,6 +213,7 @@ namespace mlx
|
||||
|
||||
void UniformBuffer::Destroy() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
m_buffers[i].Destroy();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace mlx
|
||||
{
|
||||
void TransitionImageToCorrectLayout(Image& image, VkCommandBuffer cmd)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(!image.IsInit())
|
||||
return;
|
||||
if(image.GetType() == ImageType::Color)
|
||||
@@ -21,6 +22,7 @@ namespace mlx
|
||||
DescriptorSet::DescriptorSet(const ShaderSetLayout& layout, VkDescriptorSetLayout vklayout, ShaderType shader_type)
|
||||
: m_set_layout(vklayout)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
for(auto& [binding, type] : layout.binds)
|
||||
{
|
||||
m_descriptors.emplace_back();
|
||||
@@ -35,12 +37,14 @@ namespace mlx
|
||||
DescriptorSet::DescriptorSet(VkDescriptorSetLayout layout, const std::vector<Descriptor>& descriptors)
|
||||
: m_descriptors(descriptors), m_set_layout(layout)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
m_set[i] = kvfAllocateDescriptorSet(RenderCore::Get().GetDevice(), layout);
|
||||
}
|
||||
|
||||
void DescriptorSet::SetImage(std::size_t i, std::uint32_t binding, class Image& image)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor");
|
||||
auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor)
|
||||
{
|
||||
@@ -61,6 +65,7 @@ namespace mlx
|
||||
|
||||
void DescriptorSet::SetStorageBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor");
|
||||
auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor)
|
||||
{
|
||||
@@ -81,6 +86,7 @@ namespace mlx
|
||||
|
||||
void DescriptorSet::SetUniformBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor");
|
||||
auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor)
|
||||
{
|
||||
@@ -101,6 +107,7 @@ namespace mlx
|
||||
|
||||
void DescriptorSet::Update(std::size_t i, VkCommandBuffer cmd) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor");
|
||||
std::vector<VkWriteDescriptorSet> writes;
|
||||
std::vector<VkDescriptorBufferInfo> buffer_infos;
|
||||
@@ -141,6 +148,7 @@ namespace mlx
|
||||
|
||||
void DescriptorSet::Reallocate() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
m_set[i] = kvfAllocateDescriptorSet(RenderCore::Get().GetDevice(), m_set_layout);
|
||||
}
|
||||
|
||||
@@ -15,14 +15,18 @@
|
||||
|
||||
namespace mlx
|
||||
{
|
||||
void Image::Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, bool is_multisampled)
|
||||
void Image::Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, bool is_multisampled, std::string_view debug_name)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
m_type = type;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_format = format;
|
||||
m_tiling = tiling;
|
||||
m_is_multisampled = is_multisampled;
|
||||
#ifdef DEBUG
|
||||
m_debug_name = std::move(debug_name);
|
||||
#endif
|
||||
|
||||
VmaAllocationCreateInfo alloc_info{};
|
||||
alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||
@@ -41,21 +45,39 @@ namespace mlx
|
||||
image_info.usage = usage;
|
||||
image_info.samples = (m_is_multisampled ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT);
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
m_allocation = RenderCore::Get().GetAllocator().CreateImage(&image_info, &alloc_info, m_image);
|
||||
#ifdef DEBUG
|
||||
m_allocation = RenderCore::Get().GetAllocator().CreateImage(&image_info, &alloc_info, m_image, m_debug_name.c_str());
|
||||
#else
|
||||
m_allocation = RenderCore::Get().GetAllocator().CreateImage(&image_info, &alloc_info, m_image, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Image::CreateImageView(VkImageViewType type, VkImageAspectFlags aspect_flags, int layer_count) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
m_image_view = kvfCreateImageView(RenderCore::Get().GetDevice(), m_image, m_format, type, aspect_flags, layer_count);
|
||||
#ifdef DEBUG
|
||||
if constexpr(RenderCore::HAS_DEBUG_UTILS_FUNCTIONS)
|
||||
{
|
||||
VkDebugUtilsObjectNameInfoEXT name_info{};
|
||||
name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||
name_info.objectType = VK_OBJECT_TYPE_IMAGE_VIEW;
|
||||
name_info.objectHandle = reinterpret_cast<std::uint64_t>(m_image_view);
|
||||
name_info.pObjectName = m_debug_name.c_str();
|
||||
RenderCore::Get().vkSetDebugUtilsObjectNameEXT(RenderCore::Get().GetDevice(), &name_info);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Image::CreateSampler() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
m_sampler = kvfCreateSampler(RenderCore::Get().GetDevice(), VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_MIPMAP_MODE_NEAREST);
|
||||
}
|
||||
|
||||
void Image::TransitionLayout(VkImageLayout new_layout, VkCommandBuffer cmd)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(new_layout == m_layout)
|
||||
return;
|
||||
bool is_single_time_cmd_buffer = (cmd == VK_NULL_HANDLE);
|
||||
@@ -74,6 +96,7 @@ namespace mlx
|
||||
|
||||
void Image::Clear(VkCommandBuffer cmd, Vec4f color)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
VkImageSubresourceRange subresource_range{};
|
||||
subresource_range.baseMipLevel = 0;
|
||||
subresource_range.layerCount = 1;
|
||||
@@ -100,6 +123,7 @@ namespace mlx
|
||||
|
||||
void Image::DestroySampler() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_sampler != VK_NULL_HANDLE)
|
||||
kvfDestroySampler(RenderCore::Get().GetDevice(), m_sampler);
|
||||
m_sampler = VK_NULL_HANDLE;
|
||||
@@ -107,6 +131,7 @@ namespace mlx
|
||||
|
||||
void Image::DestroyImageView() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_image_view != VK_NULL_HANDLE)
|
||||
kvfDestroyImageView(RenderCore::Get().GetDevice(), m_image_view);
|
||||
m_image_view = VK_NULL_HANDLE;
|
||||
@@ -114,14 +139,45 @@ namespace mlx
|
||||
|
||||
void Image::Destroy() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
DestroySampler();
|
||||
DestroyImageView();
|
||||
|
||||
if(m_image != VK_NULL_HANDLE)
|
||||
RenderCore::Get().GetAllocator().DestroyImage(m_allocation, m_image);
|
||||
{
|
||||
#ifdef DEBUG
|
||||
RenderCore::Get().GetAllocator().DestroyImage(m_allocation, m_image, m_debug_name.c_str());
|
||||
#else
|
||||
RenderCore::Get().GetAllocator().DestroyImage(m_allocation, m_image, nullptr);
|
||||
#endif
|
||||
}
|
||||
m_image = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void Texture::Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format, bool is_multisampled, std::string_view debug_name)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
Image::Init(ImageType::Color, width, height, format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, is_multisampled, std::move(debug_name));
|
||||
Image::CreateImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
Image::CreateSampler();
|
||||
if(pixels)
|
||||
{
|
||||
GPUBuffer staging_buffer;
|
||||
std::size_t size = width * height * kvfFormatSize(format);
|
||||
staging_buffer.Init(BufferType::Staging, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, std::move(pixels), debug_name);
|
||||
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 });
|
||||
RenderCore::Get().vkEndCommandBuffer(cmd);
|
||||
VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice());
|
||||
kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence);
|
||||
kvfDestroyFence(RenderCore::Get().GetDevice(), fence);
|
||||
staging_buffer.Destroy();
|
||||
}
|
||||
TransitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void Texture::SetPixel(int x, int y, std::uint32_t color) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
@@ -150,6 +206,7 @@ namespace mlx
|
||||
|
||||
void Texture::Update(VkCommandBuffer cmd)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(!m_has_been_modified)
|
||||
return;
|
||||
std::memcpy(m_staging_buffer->GetMap(), m_cpu_buffer.data(), m_cpu_buffer.size() * kvfFormatSize(m_format));
|
||||
@@ -167,10 +224,12 @@ namespace mlx
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_staging_buffer.has_value())
|
||||
return;
|
||||
DebugLog("Texture : enabling CPU mapping");
|
||||
#ifdef DEBUG
|
||||
DebugLog("Texture : enabling CPU mapping for '%'", m_debug_name);
|
||||
#endif
|
||||
m_staging_buffer.emplace();
|
||||
std::size_t size = m_width * m_height * kvfFormatSize(m_format);
|
||||
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, {}, m_debug_name);
|
||||
|
||||
VkImageLayout old_layout = m_layout;
|
||||
VkCommandBuffer cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
|
||||
@@ -199,7 +258,7 @@ namespace mlx
|
||||
}
|
||||
if(stbi_is_hdr(filename.c_str()))
|
||||
{
|
||||
Error("Texture : unsupported image format %", file);
|
||||
Error("Texture : unsupported image format % (HDR image)", file);
|
||||
return nullptr;
|
||||
}
|
||||
int dummy_w;
|
||||
@@ -210,7 +269,7 @@ namespace mlx
|
||||
std::memcpy(buffer.GetData(), data, buffer.GetSize());
|
||||
Texture* texture;
|
||||
|
||||
try { texture = new Texture(buffer, (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h)); }
|
||||
try { texture = new Texture(buffer, (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h), VK_FORMAT_R8G8B8A8_SRGB, false, std::move(filename)); }
|
||||
catch(...) { return NULL; }
|
||||
|
||||
stbi_image_free(data);
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace mlx
|
||||
{
|
||||
void GPUAllocator::Init() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
VmaVulkanFunctions vma_vulkan_func{};
|
||||
vma_vulkan_func.vkAllocateMemory = RenderCore::Get().vkAllocateMemory;
|
||||
vma_vulkan_func.vkBindBufferMemory = RenderCore::Get().vkBindBufferMemory;
|
||||
@@ -63,6 +64,15 @@ namespace mlx
|
||||
kvfCheckVk(vmaCreateBuffer(m_allocator, binfo, vinfo, &buffer, &allocation, nullptr));
|
||||
if(name != nullptr)
|
||||
{
|
||||
if constexpr(RenderCore::HAS_DEBUG_UTILS_FUNCTIONS)
|
||||
{
|
||||
VkDebugUtilsObjectNameInfoEXT name_info{};
|
||||
name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||
name_info.objectType = VK_OBJECT_TYPE_BUFFER;
|
||||
name_info.objectHandle = reinterpret_cast<std::uint64_t>(buffer);
|
||||
name_info.pObjectName = name;
|
||||
RenderCore::Get().vkSetDebugUtilsObjectNameEXT(RenderCore::Get().GetDevice(), &name_info);
|
||||
}
|
||||
vmaSetAllocationName(m_allocator, allocation, name);
|
||||
}
|
||||
DebugLog("Graphics Allocator : created new buffer '%'", name);
|
||||
@@ -70,12 +80,15 @@ namespace mlx
|
||||
return allocation;
|
||||
}
|
||||
|
||||
void GPUAllocator::DestroyBuffer(VmaAllocation allocation, VkBuffer buffer) noexcept
|
||||
void GPUAllocator::DestroyBuffer(VmaAllocation allocation, VkBuffer buffer, const char* name) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
RenderCore::Get().WaitDeviceIdle();
|
||||
vmaDestroyBuffer(m_allocator, buffer, allocation);
|
||||
DebugLog("Graphics Allocator : destroyed buffer");
|
||||
if(name != nullptr)
|
||||
DebugLog("Graphics Allocator : destroyed buffer '%'", name);
|
||||
else
|
||||
DebugLog("Graphics Allocator : destroyed buffer");
|
||||
m_active_buffers_allocations--;
|
||||
}
|
||||
|
||||
@@ -86,6 +99,15 @@ namespace mlx
|
||||
kvfCheckVk(vmaCreateImage(m_allocator, iminfo, vinfo, &image, &allocation, nullptr));
|
||||
if(name != nullptr)
|
||||
{
|
||||
if constexpr(RenderCore::HAS_DEBUG_UTILS_FUNCTIONS)
|
||||
{
|
||||
VkDebugUtilsObjectNameInfoEXT name_info{};
|
||||
name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||
name_info.objectType = VK_OBJECT_TYPE_IMAGE;
|
||||
name_info.objectHandle = reinterpret_cast<std::uint64_t>(image);
|
||||
name_info.pObjectName = name;
|
||||
RenderCore::Get().vkSetDebugUtilsObjectNameEXT(RenderCore::Get().GetDevice(), &name_info);
|
||||
}
|
||||
vmaSetAllocationName(m_allocator, allocation, name);
|
||||
}
|
||||
DebugLog("Graphics Allocator : created new image '%'", name);
|
||||
@@ -93,12 +115,15 @@ namespace mlx
|
||||
return allocation;
|
||||
}
|
||||
|
||||
void GPUAllocator::DestroyImage(VmaAllocation allocation, VkImage image) noexcept
|
||||
void GPUAllocator::DestroyImage(VmaAllocation allocation, VkImage image, const char* name) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
RenderCore::Get().WaitDeviceIdle();
|
||||
vmaDestroyImage(m_allocator, image, allocation);
|
||||
DebugLog("Graphics Allocator : destroyed image");
|
||||
if(name != nullptr)
|
||||
DebugLog("Graphics Allocator : destroyed image '%'", name);
|
||||
else
|
||||
DebugLog("Graphics Allocator : destroyed image");
|
||||
m_active_images_allocations--;
|
||||
}
|
||||
|
||||
@@ -141,6 +166,7 @@ namespace mlx
|
||||
|
||||
void GPUAllocator::Destroy() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_active_images_allocations != 0)
|
||||
Error("Graphics allocator : some user-dependant allocations were not freed before destroying the display (% active allocations). You may have not destroyed all the MLX resources you've created", m_active_images_allocations);
|
||||
else if(m_active_buffers_allocations != 0)
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace mlx
|
||||
{
|
||||
void GraphicPipeline::Init(const GraphicPipelineDescriptor& descriptor)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(!descriptor.vertex_shader || !descriptor.fragment_shader)
|
||||
FatalError("Vulkan : invalid shaders");
|
||||
|
||||
@@ -62,6 +63,7 @@ namespace mlx
|
||||
|
||||
bool GraphicPipeline::BindPipeline(VkCommandBuffer command_buffer, std::size_t framebuffer_index, std::array<float, 4> clear) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
TransitionAttachments(command_buffer);
|
||||
VkFramebuffer fb = m_framebuffers[framebuffer_index];
|
||||
VkExtent2D fb_extent = kvfGetFramebufferSize(fb);
|
||||
@@ -98,11 +100,13 @@ namespace mlx
|
||||
|
||||
void GraphicPipeline::EndPipeline(VkCommandBuffer command_buffer) noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
RenderCore::Get().vkCmdEndRenderPass(command_buffer);
|
||||
}
|
||||
|
||||
void GraphicPipeline::Destroy() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
p_vertex_shader.reset();
|
||||
p_fragment_shader.reset();
|
||||
for(auto& fb : m_framebuffers)
|
||||
@@ -124,6 +128,7 @@ namespace mlx
|
||||
|
||||
void GraphicPipeline::CreateFramebuffers(const std::vector<NonOwningPtr<Texture>>& render_targets, bool clear_attachments)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
std::vector<VkAttachmentDescription> attachments;
|
||||
std::vector<VkImageView> attachment_views;
|
||||
if(p_renderer)
|
||||
@@ -167,6 +172,7 @@ namespace mlx
|
||||
|
||||
void GraphicPipeline::TransitionAttachments(VkCommandBuffer cmd)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(p_depth)
|
||||
p_depth->TransitionLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, cmd);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace mlx
|
||||
{
|
||||
Shader::Shader(const std::vector<std::uint8_t>& bytecode, ShaderType type, ShaderLayout layout) : m_layout(std::move(layout)), m_bytecode(bytecode)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
switch(type)
|
||||
{
|
||||
case ShaderType::Vertex : m_stage = VK_SHADER_STAGE_VERTEX_BIT; break;
|
||||
@@ -22,6 +23,7 @@ namespace mlx
|
||||
|
||||
void Shader::GeneratePipelineLayout(ShaderLayout layout)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
for(auto& [n, set] : layout.set_layouts)
|
||||
{
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings(set.binds.size());
|
||||
@@ -55,6 +57,7 @@ namespace mlx
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
kvfDestroyShaderModule(RenderCore::Get().GetDevice(), m_module);
|
||||
DebugLog("Vulkan : shader module destroyed");
|
||||
for(auto& layout : m_set_layouts)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace mlx
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void ValidationWarningCallback(const char* message) noexcept
|
||||
void WarningCallback(const char* message) noexcept
|
||||
{
|
||||
Logs::Report(LogType::Warning, 0, "", "", message);
|
||||
std::cout << std::endl;
|
||||
@@ -54,8 +54,9 @@ namespace mlx
|
||||
LoadKVFGlobalVulkanFunctionPointers();
|
||||
|
||||
kvfSetErrorCallback(&ErrorCallback);
|
||||
kvfSetWarningCallback(&WarningCallback);
|
||||
kvfSetValidationErrorCallback(&ValidationErrorCallback);
|
||||
kvfSetValidationWarningCallback(&ValidationWarningCallback);
|
||||
kvfSetValidationWarningCallback(&WarningCallback);
|
||||
|
||||
//kvfAddLayer("VK_LAYER_MESA_overlay");
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace mlx
|
||||
|
||||
void Render2DPass::Init()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
ShaderLayout vertex_shader_layout(
|
||||
{
|
||||
{ 0,
|
||||
@@ -64,7 +65,7 @@ namespace mlx
|
||||
p_texture_set = std::make_shared<DescriptorSet>(p_fragment_shader->GetShaderLayout().set_layouts[0].second, p_fragment_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment);
|
||||
|
||||
p_viewer_data_buffer = std::make_shared<UniformBuffer>();
|
||||
p_viewer_data_buffer->Init(sizeof(ViewerData));
|
||||
p_viewer_data_buffer->Init(sizeof(ViewerData), "mlx_2d_pass_viewer_data");
|
||||
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
p_viewer_data_set->SetUniformBuffer(i, 0, p_viewer_data_buffer->Get(i));
|
||||
@@ -74,6 +75,7 @@ namespace mlx
|
||||
|
||||
void Render2DPass::Pass(Scene& scene, Renderer& renderer, Texture& render_target)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_pipeline.GetPipeline() == VK_NULL_HANDLE)
|
||||
{
|
||||
GraphicPipelineDescriptor pipeline_descriptor;
|
||||
@@ -115,6 +117,7 @@ namespace mlx
|
||||
|
||||
void Render2DPass::Destroy()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
m_pipeline.Destroy();
|
||||
p_vertex_shader.reset();
|
||||
p_fragment_shader.reset();
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace mlx
|
||||
{
|
||||
void FinalPass::Init()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
ShaderLayout vertex_shader_layout(
|
||||
{}, {}
|
||||
);
|
||||
@@ -44,6 +45,7 @@ namespace mlx
|
||||
|
||||
void FinalPass::Pass([[maybe_unused]] Scene& scene, Renderer& renderer, Texture& render_target)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
if(m_pipeline.GetPipeline() == VK_NULL_HANDLE)
|
||||
{
|
||||
GraphicPipelineDescriptor pipeline_descriptor;
|
||||
@@ -70,6 +72,7 @@ namespace mlx
|
||||
|
||||
void FinalPass::Destroy()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
m_pipeline.Destroy();
|
||||
p_vertex_shader.reset();
|
||||
p_fragment_shader.reset();
|
||||
|
||||
@@ -21,13 +21,21 @@ namespace mlx
|
||||
{
|
||||
m_main_render_texture.Destroy();
|
||||
auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain());
|
||||
m_main_render_texture.Init({}, extent.width, extent.height);
|
||||
#ifdef DEBUG
|
||||
m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_renderpasses_target");
|
||||
#else
|
||||
m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, {});
|
||||
#endif
|
||||
}
|
||||
};
|
||||
EventBus::RegisterListener({ functor, "__MlxRenderPasses" });
|
||||
auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain());
|
||||
|
||||
m_main_render_texture.Init({}, extent.width, extent.height);
|
||||
#ifdef DEBUG
|
||||
m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, "mlx_renderpasses_target");
|
||||
#else
|
||||
m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_SRGB, false, {});
|
||||
#endif
|
||||
}
|
||||
|
||||
m_main_render_texture.Clear(renderer.GetActiveCommandBuffer(), Vec4f{ 0.0f, 0.0f, 0.0f, 1.0f });
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace mlx
|
||||
|
||||
void Renderer::Init(NonOwningPtr<Window> window)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
func::function<void(const EventBase&)> functor = [this](const EventBase& event)
|
||||
{
|
||||
if(event.What() == Event::ResizeEventCode)
|
||||
@@ -56,6 +57,7 @@ namespace mlx
|
||||
|
||||
bool Renderer::BeginFrame()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
kvfWaitForFence(RenderCore::Get().GetDevice(), m_cmd_fences[m_current_frame_index]);
|
||||
VkResult result = RenderCore::Get().vkAcquireNextImageKHR(RenderCore::Get().GetDevice(), m_swapchain, UINT64_MAX, m_image_available_semaphores[m_current_frame_index], VK_NULL_HANDLE, &m_swapchain_image_index);
|
||||
if(result == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
@@ -78,6 +80,7 @@ namespace mlx
|
||||
|
||||
void Renderer::EndFrame()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
|
||||
kvfEndCommandBuffer(m_cmd_buffers[m_current_frame_index]);
|
||||
kvfSubmitCommandBuffer(RenderCore::Get().GetDevice(), m_cmd_buffers[m_current_frame_index], KVF_GRAPHICS_QUEUE, m_render_finished_semaphores[m_current_frame_index], m_image_available_semaphores[m_current_frame_index], m_cmd_fences[m_current_frame_index], wait_stages);
|
||||
@@ -95,6 +98,7 @@ namespace mlx
|
||||
|
||||
void Renderer::CreateSwapchain()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
Vec2ui drawable_size = p_window->GetVulkanDrawableSize();
|
||||
VkExtent2D extent = { drawable_size.x, drawable_size.y };
|
||||
m_swapchain = kvfCreateSwapchainKHR(RenderCore::Get().GetDevice(), RenderCore::Get().GetPhysicalDevice(), m_surface, extent, false);
|
||||
@@ -105,7 +109,11 @@ namespace mlx
|
||||
RenderCore::Get().vkGetSwapchainImagesKHR(RenderCore::Get().GetDevice(), m_swapchain, &images_count, tmp.data());
|
||||
for(std::size_t i = 0; i < images_count; i++)
|
||||
{
|
||||
m_swapchain_images[i].Init(tmp[i], kvfGetSwapchainImagesFormat(m_swapchain), extent.width, extent.height);
|
||||
#ifdef DEBUG
|
||||
m_swapchain_images[i].Init(tmp[i], kvfGetSwapchainImagesFormat(m_swapchain), extent.width, extent.height, VK_IMAGE_LAYOUT_UNDEFINED, "mlx_swapchain_image_" + std::to_string(i));
|
||||
#else
|
||||
m_swapchain_images[i].Init(tmp[i], kvfGetSwapchainImagesFormat(m_swapchain), extent.width, extent.height, VK_IMAGE_LAYOUT_UNDEFINED, {});
|
||||
#endif
|
||||
m_swapchain_images[i].TransitionLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
m_swapchain_images[i].CreateImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
@@ -114,6 +122,7 @@ namespace mlx
|
||||
|
||||
void Renderer::DestroySwapchain()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
RenderCore::Get().WaitDeviceIdle();
|
||||
for(Image& img : m_swapchain_images)
|
||||
img.DestroyImageView();
|
||||
@@ -123,6 +132,7 @@ namespace mlx
|
||||
|
||||
void Renderer::Destroy() noexcept
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
RenderCore::Get().WaitDeviceIdle();
|
||||
|
||||
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
|
||||
|
||||
@@ -8,16 +8,19 @@ namespace mlx
|
||||
{
|
||||
void SceneRenderer::Init()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
m_passes.Init();
|
||||
}
|
||||
|
||||
void SceneRenderer::Render(Scene& scene, Renderer& renderer)
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
m_passes.Pass(scene, renderer);
|
||||
}
|
||||
|
||||
void SceneRenderer::Destroy()
|
||||
{
|
||||
MLX_PROFILE_FUNCTION();
|
||||
m_passes.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user