mirror of
https://github.com/slendidev/lunar.git
synced 2025-12-14 03:49:51 +02:00
@@ -352,6 +352,10 @@ auto VulkanRenderer::descriptors_init() -> void
|
|||||||
.add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
.add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
||||||
.build(m_logger, m_vkb.dev,
|
.build(m_logger, m_vkb.dev,
|
||||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
m_vk.deletion_queue.emplace([&]() {
|
||||||
|
vkDestroyDescriptorSetLayout(
|
||||||
|
m_vkb.dev, m_vk.gpu_scene_data_descriptor_layout, nullptr);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::pipelines_init() -> void
|
auto VulkanRenderer::pipelines_init() -> void
|
||||||
@@ -628,6 +632,59 @@ auto VulkanRenderer::default_data_init() -> void
|
|||||||
destroy_buffer(m_vk.rectangle.index_buffer);
|
destroy_buffer(m_vk.rectangle.index_buffer);
|
||||||
destroy_buffer(m_vk.rectangle.vertex_buffer);
|
destroy_buffer(m_vk.rectangle.vertex_buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
// Solid color images
|
||||||
|
auto const white = smath::pack_unorm4x8(smath::Vec4 { 1, 1, 1, 1 });
|
||||||
|
m_vk.white_image = create_image(&white, VkExtent3D { 1, 1, 1 },
|
||||||
|
VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
|
||||||
|
auto const black = smath::pack_unorm4x8(smath::Vec4 { 0, 0, 0, 1 });
|
||||||
|
m_vk.black_image = create_image(&black, VkExtent3D { 1, 1, 1 },
|
||||||
|
VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
|
||||||
|
auto const gray
|
||||||
|
= smath::pack_unorm4x8(smath::Vec4 { 0.6f, 0.6f, 0.6f, 1 });
|
||||||
|
m_vk.gray_image = create_image(&gray, VkExtent3D { 1, 1, 1 },
|
||||||
|
VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
|
||||||
|
// Error checkerboard image
|
||||||
|
auto const magenta = smath::pack_unorm4x8(smath::Vec4 { 1, 0, 1, 1 });
|
||||||
|
std::array<uint32_t, 16 * 16> checkerboard;
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
checkerboard[y * 16 + x]
|
||||||
|
= ((x % 2) ^ (y % 2)) ? magenta : black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_vk.error_image
|
||||||
|
= create_image(checkerboard.data(), VkExtent3D { 16, 16, 1 },
|
||||||
|
VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSamplerCreateInfo sampler_ci {};
|
||||||
|
sampler_ci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||||
|
sampler_ci.pNext = nullptr;
|
||||||
|
|
||||||
|
sampler_ci.magFilter = VK_FILTER_NEAREST;
|
||||||
|
sampler_ci.minFilter = VK_FILTER_NEAREST;
|
||||||
|
vkCreateSampler(
|
||||||
|
m_vkb.dev, &sampler_ci, nullptr, &m_vk.default_sampler_nearest);
|
||||||
|
|
||||||
|
sampler_ci.magFilter = VK_FILTER_LINEAR;
|
||||||
|
sampler_ci.minFilter = VK_FILTER_LINEAR;
|
||||||
|
vkCreateSampler(
|
||||||
|
m_vkb.dev, &sampler_ci, nullptr, &m_vk.default_sampler_linear);
|
||||||
|
|
||||||
|
m_vk.deletion_queue.emplace([&]() {
|
||||||
|
vkDestroySampler(m_vkb.dev, m_vk.default_sampler_linear, nullptr);
|
||||||
|
vkDestroySampler(m_vkb.dev, m_vk.default_sampler_nearest, nullptr);
|
||||||
|
|
||||||
|
destroy_image(m_vk.error_image);
|
||||||
|
destroy_image(m_vk.gray_image);
|
||||||
|
destroy_image(m_vk.black_image);
|
||||||
|
destroy_image(m_vk.white_image);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::render() -> void
|
auto VulkanRenderer::render() -> void
|
||||||
@@ -925,60 +982,22 @@ auto VulkanRenderer::create_draw_image(uint32_t width, uint32_t height) -> void
|
|||||||
{
|
{
|
||||||
destroy_draw_image();
|
destroy_draw_image();
|
||||||
|
|
||||||
m_vk.draw_image.format = VK_FORMAT_R16G16B16A16_SFLOAT;
|
auto const flags { VK_IMAGE_USAGE_TRANSFER_SRC_BIT
|
||||||
m_vk.draw_image.extent = {
|
| VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT
|
||||||
width,
|
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT };
|
||||||
height,
|
m_vk.draw_image = create_image(
|
||||||
1,
|
{ width, height, 1 }, VK_FORMAT_R16G16B16A16_SFLOAT, flags);
|
||||||
};
|
|
||||||
|
|
||||||
VkImageCreateInfo rimg_ci { vkinit::image_create_info(
|
|
||||||
m_vk.draw_image.format,
|
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
|
||||||
| VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
|
||||||
m_vk.draw_image.extent) };
|
|
||||||
VmaAllocationCreateInfo rimg_alloci {};
|
|
||||||
rimg_alloci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
|
||||||
rimg_alloci.requiredFlags
|
|
||||||
= VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
||||||
|
|
||||||
vmaCreateImage(m_vk.allocator, &rimg_ci, &rimg_alloci,
|
|
||||||
&m_vk.draw_image.image, &m_vk.draw_image.allocation, nullptr);
|
|
||||||
|
|
||||||
VkImageViewCreateInfo rview_ci
|
|
||||||
= vkinit::imageview_create_info(m_vk.draw_image.format,
|
|
||||||
m_vk.draw_image.image, VK_IMAGE_ASPECT_COLOR_BIT);
|
|
||||||
VK_CHECK(m_logger,
|
|
||||||
vkCreateImageView(
|
|
||||||
m_vkb.dev, &rview_ci, nullptr, &m_vk.draw_image.image_view));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::create_depth_image(uint32_t width, uint32_t height) -> void
|
auto VulkanRenderer::create_depth_image(uint32_t width, uint32_t height) -> void
|
||||||
{
|
{
|
||||||
destroy_depth_image();
|
destroy_depth_image();
|
||||||
|
|
||||||
m_vk.depth_image.format = VK_FORMAT_D32_SFLOAT;
|
auto const flags { VK_IMAGE_USAGE_TRANSFER_SRC_BIT
|
||||||
m_vk.depth_image.extent = { width, height, 1 };
|
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||||
|
| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT };
|
||||||
VkImageCreateInfo rimg_ci { vkinit::image_create_info(
|
m_vk.depth_image
|
||||||
m_vk.depth_image.format,
|
= create_image({ width, height, 1 }, VK_FORMAT_D32_SFLOAT, flags);
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
|
||||||
| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
|
||||||
m_vk.depth_image.extent) };
|
|
||||||
VmaAllocationCreateInfo rimg_alloci {};
|
|
||||||
rimg_alloci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
|
||||||
rimg_alloci.requiredFlags
|
|
||||||
= VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
||||||
|
|
||||||
vmaCreateImage(m_vk.allocator, &rimg_ci, &rimg_alloci,
|
|
||||||
&m_vk.depth_image.image, &m_vk.depth_image.allocation, nullptr);
|
|
||||||
|
|
||||||
VkImageViewCreateInfo rview_ci
|
|
||||||
= vkinit::imageview_create_info(m_vk.depth_image.format,
|
|
||||||
m_vk.depth_image.image, VK_IMAGE_ASPECT_DEPTH_BIT);
|
|
||||||
VK_CHECK(m_logger,
|
|
||||||
vkCreateImageView(
|
|
||||||
m_vkb.dev, &rview_ci, nullptr, &m_vk.depth_image.image_view));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::destroy_depth_image() -> void
|
auto VulkanRenderer::destroy_depth_image() -> void
|
||||||
@@ -1061,6 +1080,112 @@ auto VulkanRenderer::destroy_swapchain() -> void
|
|||||||
m_vk.swapchain_extent = { 0, 0 };
|
m_vk.swapchain_extent = { 0, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::create_image(VkExtent3D size, VkFormat format,
|
||||||
|
VkImageUsageFlags flags, bool mipmapped) -> AllocatedImage
|
||||||
|
{
|
||||||
|
AllocatedImage new_image;
|
||||||
|
new_image.format = format;
|
||||||
|
new_image.extent = size;
|
||||||
|
|
||||||
|
auto img_ci { vkinit::image_create_info(format, flags, size) };
|
||||||
|
if (mipmapped) {
|
||||||
|
img_ci.mipLevels = static_cast<uint32_t>(std::floor(
|
||||||
|
std::log2(std::max(size.width, size.height))))
|
||||||
|
+ 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VmaAllocationCreateInfo alloc_ci {};
|
||||||
|
alloc_ci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||||
|
alloc_ci.requiredFlags
|
||||||
|
= VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
|
VK_CHECK(m_logger,
|
||||||
|
vmaCreateImage(m_vk.allocator, &img_ci, &alloc_ci, &new_image.image,
|
||||||
|
&new_image.allocation, nullptr));
|
||||||
|
|
||||||
|
VkImageAspectFlags aspect_flag { VK_IMAGE_ASPECT_COLOR_BIT };
|
||||||
|
if (format == VK_FORMAT_D32_SFLOAT) {
|
||||||
|
aspect_flag = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const view_ci { vkinit::imageview_create_info(
|
||||||
|
format, new_image.image, aspect_flag) };
|
||||||
|
VK_CHECK(m_logger,
|
||||||
|
vkCreateImageView(m_vkb.dev, &view_ci, nullptr, &new_image.image_view));
|
||||||
|
|
||||||
|
return new_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::create_image(void const *data, VkExtent3D size,
|
||||||
|
VkFormat format, VkImageUsageFlags flags, bool mipmapped) -> AllocatedImage
|
||||||
|
{
|
||||||
|
size_t data_size {
|
||||||
|
static_cast<uint32_t>(size.depth) * static_cast<uint32_t>(size.width)
|
||||||
|
* static_cast<uint32_t>(size.height) * 4,
|
||||||
|
};
|
||||||
|
auto const upload_buffer {
|
||||||
|
create_buffer(data_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
VMA_MEMORY_USAGE_CPU_TO_GPU),
|
||||||
|
};
|
||||||
|
|
||||||
|
VmaAllocationInfo info {};
|
||||||
|
vmaGetAllocationInfo(m_vk.allocator, upload_buffer.allocation, &info);
|
||||||
|
|
||||||
|
void *mapped_data { reinterpret_cast<GPUSceneData *>(info.pMappedData) };
|
||||||
|
if (!mapped_data) {
|
||||||
|
VkResult res = vmaMapMemory(
|
||||||
|
m_vk.allocator, upload_buffer.allocation, (void **)&mapped_data);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
}
|
||||||
|
defer({
|
||||||
|
if (info.pMappedData == nullptr) {
|
||||||
|
vmaUnmapMemory(m_vk.allocator, upload_buffer.allocation);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
memcpy(mapped_data, data, data_size);
|
||||||
|
|
||||||
|
auto const new_image {
|
||||||
|
create_image(size, format,
|
||||||
|
flags | VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||||
|
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
mipmapped),
|
||||||
|
};
|
||||||
|
|
||||||
|
immediate_submit([&](VkCommandBuffer cmd) {
|
||||||
|
vkutil::transition_image(cmd, new_image.image,
|
||||||
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
|
VkBufferImageCopy copy_region {};
|
||||||
|
copy_region.bufferOffset = 0;
|
||||||
|
copy_region.bufferRowLength = 0;
|
||||||
|
copy_region.bufferImageHeight = 0;
|
||||||
|
|
||||||
|
copy_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
copy_region.imageSubresource.mipLevel = 0;
|
||||||
|
copy_region.imageSubresource.baseArrayLayer = 0;
|
||||||
|
copy_region.imageSubresource.layerCount = 1;
|
||||||
|
copy_region.imageExtent = size;
|
||||||
|
|
||||||
|
vkCmdCopyBufferToImage(cmd, upload_buffer.buffer, new_image.image,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region);
|
||||||
|
|
||||||
|
vkutil::transition_image(cmd, new_image.image,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
destroy_buffer(upload_buffer);
|
||||||
|
|
||||||
|
return new_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::destroy_image(AllocatedImage const &img) -> void
|
||||||
|
{
|
||||||
|
vkDestroyImageView(m_vkb.dev, img.image_view, nullptr);
|
||||||
|
vmaDestroyImage(m_vk.allocator, img.image, img.allocation);
|
||||||
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::create_buffer(size_t alloc_size, VkBufferUsageFlags usage,
|
auto VulkanRenderer::create_buffer(size_t alloc_size, VkBufferUsageFlags usage,
|
||||||
VmaMemoryUsage memory_usage) -> AllocatedBuffer
|
VmaMemoryUsage memory_usage) -> AllocatedBuffer
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ private:
|
|||||||
auto destroy_depth_image() -> void;
|
auto destroy_depth_image() -> void;
|
||||||
auto recreate_swapchain(uint32_t width, uint32_t height) -> void;
|
auto recreate_swapchain(uint32_t width, uint32_t height) -> void;
|
||||||
auto destroy_swapchain() -> void;
|
auto destroy_swapchain() -> void;
|
||||||
|
auto create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags flags,
|
||||||
|
bool mipmapped = false) -> AllocatedImage;
|
||||||
|
auto create_image(void const *data, VkExtent3D size, VkFormat format,
|
||||||
|
VkImageUsageFlags flags, bool mipmapped = false) -> AllocatedImage;
|
||||||
|
auto destroy_image(AllocatedImage const &img) -> void;
|
||||||
|
|
||||||
auto create_buffer(size_t alloc_size, VkBufferUsageFlags usage,
|
auto create_buffer(size_t alloc_size, VkBufferUsageFlags usage,
|
||||||
VmaMemoryUsage memory_usage) -> AllocatedBuffer;
|
VmaMemoryUsage memory_usage) -> AllocatedBuffer;
|
||||||
@@ -129,6 +134,14 @@ private:
|
|||||||
uint64_t frame_number { 0 };
|
uint64_t frame_number { 0 };
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Mesh>> test_meshes;
|
std::vector<std::shared_ptr<Mesh>> test_meshes;
|
||||||
|
|
||||||
|
AllocatedImage white_image {};
|
||||||
|
AllocatedImage black_image {};
|
||||||
|
AllocatedImage gray_image {};
|
||||||
|
AllocatedImage error_image {};
|
||||||
|
|
||||||
|
VkSampler default_sampler_linear;
|
||||||
|
VkSampler default_sampler_nearest;
|
||||||
} m_vk;
|
} m_vk;
|
||||||
|
|
||||||
SDL_Window *m_window { nullptr };
|
SDL_Window *m_window { nullptr };
|
||||||
|
|||||||
Reference in New Issue
Block a user