Added ImageManager and ported Box.
- BufferManager can construct UniformBuffers - Box uses Managers for all the tasks.
This commit is contained in:
parent
9ca5751a78
commit
88d8a2acc2
|
|
@ -5,4 +5,5 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
target_sources(aster_core
|
target_sources(aster_core
|
||||||
INTERFACE
|
INTERFACE
|
||||||
"manager.h"
|
"manager.h"
|
||||||
"buffer_manager.h")
|
"buffer_manager.h"
|
||||||
|
"image_manager.h")
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,6 @@ class BufferManager final : public Manager<Buffer>
|
||||||
BufferManager(const Device *device, const u32 maxCount);
|
BufferManager(const Device *device, const u32 maxCount);
|
||||||
|
|
||||||
Handle CreateStorageBuffer(usize size, cstr name = nullptr);
|
Handle CreateStorageBuffer(usize size, cstr name = nullptr);
|
||||||
|
Handle CreateUniformBuffer(usize size, cstr name = nullptr);
|
||||||
};
|
};
|
||||||
} // namespace systems
|
} // namespace systems
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
// =============================================
|
||||||
|
// Aster: image_manager.h
|
||||||
|
// Copyright (c) 2020-2024 Anish Bhobe
|
||||||
|
// =============================================
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "aster/aster.h"
|
||||||
|
#include "aster/core/image.h"
|
||||||
|
#include "manager.h"
|
||||||
|
|
||||||
|
namespace systems
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Texture2DCreateInfo
|
||||||
|
{
|
||||||
|
vk::Format m_Format = vk::Format::eUndefined;
|
||||||
|
vk::Extent2D m_Extent = {};
|
||||||
|
cstr m_Name = nullptr;
|
||||||
|
bool m_IsSampled = true;
|
||||||
|
bool m_IsMipMapped = false;
|
||||||
|
bool m_IsStorage = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TextureCubeCreateInfo
|
||||||
|
{
|
||||||
|
vk::Format m_Format = vk::Format::eUndefined;
|
||||||
|
u32 m_Side = 0;
|
||||||
|
cstr m_Name = nullptr;
|
||||||
|
bool m_IsSampled = true;
|
||||||
|
bool m_IsMipMapped = false;
|
||||||
|
bool m_IsStorage = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AttachmentCreateInfo
|
||||||
|
{
|
||||||
|
vk::Format m_Format = vk::Format::eUndefined;
|
||||||
|
vk::Extent2D m_Extent = {};
|
||||||
|
cstr m_Name = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DepthStencilImageCreateInfo
|
||||||
|
{
|
||||||
|
vk::Extent2D m_Extent = {};
|
||||||
|
cstr m_Name = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ImageHandle = Handle<Image>;
|
||||||
|
|
||||||
|
class ImageManager final : public Manager<Image>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageManager(const Device *device, const u32 maxCount);
|
||||||
|
|
||||||
|
Handle CreateTexture2D(const Texture2DCreateInfo& createInfo);
|
||||||
|
Handle CreateTextureCube(const TextureCubeCreateInfo &createInfo);
|
||||||
|
Handle CreateAttachment(const AttachmentCreateInfo &createInfo);
|
||||||
|
Handle CreateDepthStencilImage(const DepthStencilImageCreateInfo &createInfo);
|
||||||
|
};
|
||||||
|
} // namespace systems
|
||||||
|
|
@ -5,4 +5,5 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
target_sources(aster_core
|
target_sources(aster_core
|
||||||
PRIVATE
|
PRIVATE
|
||||||
"manager.cpp"
|
"manager.cpp"
|
||||||
"buffer_manager.cpp")
|
"buffer_manager.cpp"
|
||||||
|
"image_manager.cpp")
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@
|
||||||
|
|
||||||
Manager<Buffer> *Manager<Buffer>::m_Instance;
|
Manager<Buffer> *Manager<Buffer>::m_Instance;
|
||||||
|
|
||||||
systems::BufferManager::Ref
|
using namespace systems;
|
||||||
systems::BufferManager::CreateStorageBuffer(const usize size, const cstr name)
|
|
||||||
|
BufferHandle
|
||||||
|
BufferManager::CreateStorageBuffer(const usize size, const cstr name)
|
||||||
{
|
{
|
||||||
Ref object = Alloc();
|
auto [handle, object] = Alloc();
|
||||||
|
|
||||||
// TODO: Storage and Index buffer are set.
|
// TODO: Storage and Index buffer are set.
|
||||||
// This is hacky and should be improved.
|
// This is hacky and should be improved.
|
||||||
|
|
@ -22,11 +24,25 @@ systems::BufferManager::CreateStorageBuffer(const usize size, const cstr name)
|
||||||
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
||||||
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name);
|
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name);
|
||||||
|
|
||||||
return object;
|
return std::move(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
systems::BufferManager::BufferManager(const Device *device, const u32 maxCount)
|
Manager<Buffer>::Handle
|
||||||
|
BufferManager::CreateUniformBuffer(usize size, cstr name)
|
||||||
|
{
|
||||||
|
auto [handle, object] = Alloc();
|
||||||
|
|
||||||
|
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eUniformBuffer;
|
||||||
|
constexpr VmaAllocationCreateFlags createFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
|
||||||
|
VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||||
|
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
||||||
|
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name);
|
||||||
|
|
||||||
|
return std::move(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferManager::BufferManager(const Device *device, const u32 maxCount)
|
||||||
: Manager{device, maxCount}
|
: Manager{device, maxCount}
|
||||||
{
|
{
|
||||||
SetInstance(this);
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,316 @@
|
||||||
|
// =============================================
|
||||||
|
// Aster: buffer_manager.cpp
|
||||||
|
// Copyright (c) 2020-2025 Anish Bhobe
|
||||||
|
// =============================================
|
||||||
|
|
||||||
|
#include "systems/image_manager.h"
|
||||||
|
|
||||||
|
#include "core/device.h"
|
||||||
|
|
||||||
|
Manager<Image> *Manager<Image>::m_Instance;
|
||||||
|
|
||||||
|
using namespace systems;
|
||||||
|
|
||||||
|
vk::ImageCreateInfo ToImageCreateInfo(const Texture2DCreateInfo &createInfo);
|
||||||
|
vk::ImageCreateInfo ToImageCreateInfo(const TextureCubeCreateInfo &createInfo);
|
||||||
|
vk::ImageCreateInfo ToImageCreateInfo(const AttachmentCreateInfo &createInfo);
|
||||||
|
vk::ImageCreateInfo ToImageCreateInfo(const DepthStencilImageCreateInfo &createInfo);
|
||||||
|
|
||||||
|
namespace usage_flags
|
||||||
|
{
|
||||||
|
constexpr vk::ImageUsageFlags MIPMAP = vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst;
|
||||||
|
constexpr vk::ImageUsageFlags SAMPLE = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
|
||||||
|
constexpr vk::ImageUsageFlags STORAGE =
|
||||||
|
vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eTransferSrc;
|
||||||
|
constexpr vk::ImageUsageFlags COLOR_ATTACHMENT =
|
||||||
|
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc;
|
||||||
|
constexpr vk::ImageUsageFlags DEPTH_STENCIL_ATTACHMENT = vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||||
|
} // namespace usage_flags
|
||||||
|
|
||||||
|
ImageHandle
|
||||||
|
ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo)
|
||||||
|
{
|
||||||
|
constexpr VmaAllocationCreateInfo allocationCreateInfo = {
|
||||||
|
.flags = {},
|
||||||
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkImage image;
|
||||||
|
VmaAllocation allocation;
|
||||||
|
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
||||||
|
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
|
&allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
|
vk::ImageView view;
|
||||||
|
const vk::ImageViewCreateInfo imageViewCreateInfo = {
|
||||||
|
.image = image,
|
||||||
|
.viewType = vk::ImageViewType::e2D,
|
||||||
|
.format = imageCreateInfo.format,
|
||||||
|
.components = {},
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = imageCreateInfo.mipLevels,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = imageCreateInfo.arrayLayers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
|
||||||
|
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
auto [handle, object] = Alloc();
|
||||||
|
object->m_Image = image;
|
||||||
|
object->m_View = view;
|
||||||
|
object->m_Allocation = allocation;
|
||||||
|
object->m_Extent = imageCreateInfo.extent;
|
||||||
|
object->m_Flags_ = Image::OWNED_BIT | Image::VALID_BIT;
|
||||||
|
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
||||||
|
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
||||||
|
|
||||||
|
m_Device->SetName(object->m_Image, createInfo.m_Name);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageHandle
|
||||||
|
ImageManager::CreateTextureCube(const TextureCubeCreateInfo &createInfo)
|
||||||
|
{
|
||||||
|
constexpr VmaAllocationCreateInfo allocationCreateInfo = {
|
||||||
|
.flags = {},
|
||||||
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkImage image;
|
||||||
|
VmaAllocation allocation;
|
||||||
|
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
||||||
|
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
|
&allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
|
vk::ImageView view;
|
||||||
|
const vk::ImageViewCreateInfo imageViewCreateInfo = {
|
||||||
|
.image = image,
|
||||||
|
.viewType = vk::ImageViewType::eCube,
|
||||||
|
.format = imageCreateInfo.format,
|
||||||
|
.components = {},
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = imageCreateInfo.mipLevels,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = imageCreateInfo.arrayLayers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
|
||||||
|
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
auto [handle, object] = Alloc();
|
||||||
|
object->m_Image = image;
|
||||||
|
object->m_View = view;
|
||||||
|
object->m_Allocation = allocation;
|
||||||
|
object->m_Extent = imageCreateInfo.extent;
|
||||||
|
object->m_Flags_ = Image::OWNED_BIT | Image::VALID_BIT;
|
||||||
|
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
||||||
|
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
||||||
|
|
||||||
|
m_Device->SetName(object->m_Image, createInfo.m_Name);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageHandle
|
||||||
|
ImageManager::CreateAttachment(const AttachmentCreateInfo &createInfo)
|
||||||
|
{
|
||||||
|
constexpr VmaAllocationCreateInfo allocationCreateInfo = {
|
||||||
|
.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
|
||||||
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkImage image;
|
||||||
|
VmaAllocation allocation;
|
||||||
|
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
||||||
|
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
|
&allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
|
vk::ImageView view;
|
||||||
|
const vk::ImageViewCreateInfo imageViewCreateInfo = {
|
||||||
|
.image = image,
|
||||||
|
.viewType = vk::ImageViewType::e2D,
|
||||||
|
.format = imageCreateInfo.format,
|
||||||
|
.components = {},
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = imageCreateInfo.mipLevels,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = imageCreateInfo.arrayLayers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
|
||||||
|
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
auto [handle, object] = Alloc();
|
||||||
|
object->m_Image = image;
|
||||||
|
object->m_View = view;
|
||||||
|
object->m_Allocation = allocation;
|
||||||
|
object->m_Extent = imageCreateInfo.extent;
|
||||||
|
object->m_Flags_ = Image::OWNED_BIT | Image::VALID_BIT;
|
||||||
|
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
||||||
|
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
||||||
|
|
||||||
|
m_Device->SetName(object->m_Image, createInfo.m_Name);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageHandle
|
||||||
|
ImageManager::CreateDepthStencilImage(const DepthStencilImageCreateInfo &createInfo)
|
||||||
|
{
|
||||||
|
constexpr VmaAllocationCreateInfo allocationCreateInfo = {
|
||||||
|
.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
|
||||||
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkImage image;
|
||||||
|
VmaAllocation allocation;
|
||||||
|
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
||||||
|
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
|
&allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
|
vk::ImageView view;
|
||||||
|
const vk::ImageViewCreateInfo imageViewCreateInfo = {
|
||||||
|
.image = image,
|
||||||
|
.viewType = vk::ImageViewType::e2D,
|
||||||
|
.format = imageCreateInfo.format,
|
||||||
|
.components = {},
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = imageCreateInfo.mipLevels,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = imageCreateInfo.arrayLayers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
|
||||||
|
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
|
||||||
|
THEN_ABORT(result);
|
||||||
|
|
||||||
|
auto [handle, object] = Alloc();
|
||||||
|
object->m_Image = image;
|
||||||
|
object->m_View = view;
|
||||||
|
object->m_Allocation = allocation;
|
||||||
|
object->m_Extent = imageCreateInfo.extent;
|
||||||
|
object->m_Flags_ = Image::OWNED_BIT | Image::VALID_BIT;
|
||||||
|
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
||||||
|
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
||||||
|
|
||||||
|
m_Device->SetName(object->m_Image, createInfo.m_Name);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::ImageCreateInfo
|
||||||
|
ToImageCreateInfo(const Texture2DCreateInfo &createInfo)
|
||||||
|
{
|
||||||
|
auto &[format, extent, name, isSampled, isMipMapped, isStorage] = createInfo;
|
||||||
|
|
||||||
|
WARN_IF(!IsPowerOfTwo(extent.width) || !IsPowerOfTwo(extent.width), "Image {2} is {0}x{1} (Non Power of Two)",
|
||||||
|
extent.width, extent.height, name ? name : "<unnamed>");
|
||||||
|
|
||||||
|
const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
|
||||||
|
|
||||||
|
auto usage = vk::ImageUsageFlags{};
|
||||||
|
if (isSampled)
|
||||||
|
usage |= usage_flags::SAMPLE;
|
||||||
|
if (isMipMapped)
|
||||||
|
usage |= usage_flags::MIPMAP;
|
||||||
|
if (isStorage)
|
||||||
|
usage |= usage_flags::STORAGE;
|
||||||
|
|
||||||
|
return {
|
||||||
|
.imageType = vk::ImageType::e2D,
|
||||||
|
.format = format,
|
||||||
|
.extent = ToExtent3D(extent, 1),
|
||||||
|
.mipLevels = mipLevels,
|
||||||
|
.arrayLayers = 1,
|
||||||
|
.usage = usage,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::ImageCreateInfo
|
||||||
|
ToImageCreateInfo(const TextureCubeCreateInfo &createInfo)
|
||||||
|
{
|
||||||
|
auto &[format, side, name, isSampled, isMipMapped, isStorage] = createInfo;
|
||||||
|
|
||||||
|
WARN_IF(!IsPowerOfTwo(side), "ImageCube {1} is {0}x{0} (Non Power of Two)", side, name ? name : "<unnamed>");
|
||||||
|
|
||||||
|
const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(side))) : 1;
|
||||||
|
|
||||||
|
auto usage = vk::ImageUsageFlags{};
|
||||||
|
if (isSampled)
|
||||||
|
usage |= usage_flags::SAMPLE;
|
||||||
|
if (isMipMapped)
|
||||||
|
usage |= usage_flags::MIPMAP;
|
||||||
|
if (isStorage)
|
||||||
|
usage |= usage_flags::STORAGE;
|
||||||
|
|
||||||
|
return {
|
||||||
|
.flags = vk::ImageCreateFlagBits::eCubeCompatible,
|
||||||
|
.imageType = vk::ImageType::e2D,
|
||||||
|
.format = format,
|
||||||
|
.extent = {side, side, 1},
|
||||||
|
.mipLevels = mipLevels,
|
||||||
|
.arrayLayers = 6,
|
||||||
|
.usage = usage,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::ImageCreateInfo
|
||||||
|
ToImageCreateInfo(const AttachmentCreateInfo &createInfo)
|
||||||
|
{
|
||||||
|
auto &[format, extent, name] = createInfo;
|
||||||
|
|
||||||
|
constexpr auto usage = usage_flags::COLOR_ATTACHMENT;
|
||||||
|
|
||||||
|
return {
|
||||||
|
.imageType = vk::ImageType::e2D,
|
||||||
|
.format = format,
|
||||||
|
.extent = ToExtent3D(extent, 1),
|
||||||
|
.mipLevels = 1,
|
||||||
|
.arrayLayers = 1,
|
||||||
|
.usage = usage,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::ImageCreateInfo
|
||||||
|
ToImageCreateInfo(const DepthStencilImageCreateInfo &createInfo)
|
||||||
|
{
|
||||||
|
auto &[extent, name] = createInfo;
|
||||||
|
|
||||||
|
constexpr vk::Format format = vk::Format::eD24UnormS8Uint;
|
||||||
|
constexpr auto usage = usage_flags::DEPTH_STENCIL_ATTACHMENT;
|
||||||
|
|
||||||
|
return {
|
||||||
|
.imageType = vk::ImageType::e2D,
|
||||||
|
.format = format,
|
||||||
|
.extent = ToExtent3D(extent, 1),
|
||||||
|
.mipLevels = 1,
|
||||||
|
.arrayLayers = 1,
|
||||||
|
.usage = usage,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageManager::ImageManager(const Device *device, const u32 maxCount)
|
||||||
|
: Manager{device, maxCount}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,8 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
add_executable(box "box.cpp" "stb_image.h")
|
add_executable(box "box.cpp" "stb_image.h")
|
||||||
add_shader(box "shader/box.vert.glsl")
|
add_shader(box "shader/box.vert.glsl")
|
||||||
add_shader(box "shader/box.frag.glsl")
|
add_shader(box "shader/box.frag.glsl")
|
||||||
|
add_shader(box "shader/box.vs.hlsl")
|
||||||
|
add_shader(box "shader/box.ps.hlsl")
|
||||||
|
|
||||||
target_link_libraries(box PRIVATE aster_core)
|
target_link_libraries(box PRIVATE aster_core)
|
||||||
target_link_libraries(box PRIVATE util_helper)
|
target_link_libraries(box PRIVATE util_helper)
|
||||||
|
|
|
||||||
|
|
@ -9,23 +9,25 @@
|
||||||
#include "aster/core/constants.h"
|
#include "aster/core/constants.h"
|
||||||
#include "aster/core/context.h"
|
#include "aster/core/context.h"
|
||||||
#include "aster/core/device.h"
|
#include "aster/core/device.h"
|
||||||
|
#include "aster/core/image.h"
|
||||||
#include "aster/core/physical_device.h"
|
#include "aster/core/physical_device.h"
|
||||||
#include "aster/core/pipeline.h"
|
#include "aster/core/pipeline.h"
|
||||||
#include "aster/core/swapchain.h"
|
#include "aster/core/swapchain.h"
|
||||||
#include "aster/core/window.h"
|
#include "aster/core/window.h"
|
||||||
#include "aster/core/image.h"
|
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "aster/systems/buffer_manager.h"
|
||||||
|
#include "aster/systems/image_manager.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
|
|
||||||
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
||||||
constexpr auto VERTEX_SHADER_FILE = "shader/box.vert.glsl.spv";
|
constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv";
|
||||||
constexpr auto FRAGMENT_SHADER_FILE = "shader/box.frag.glsl.spv";
|
constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv";
|
||||||
|
|
||||||
struct ImageFile
|
struct ImageFile
|
||||||
{
|
{
|
||||||
|
|
@ -76,32 +78,9 @@ Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain);
|
||||||
struct Vertex
|
struct Vertex
|
||||||
{
|
{
|
||||||
vec3 m_Position;
|
vec3 m_Position;
|
||||||
|
f32 m_PositionW = 1.0;
|
||||||
vec2 m_TexCoord0;
|
vec2 m_TexCoord0;
|
||||||
|
vec2 m_Padding0_ = {0.0f, 0.0f};
|
||||||
constexpr static vk::VertexInputBindingDescription
|
|
||||||
GetBinding(const u32 binding)
|
|
||||||
{
|
|
||||||
return {.binding = binding, .stride = sizeof(Vertex), .inputRate = vk::VertexInputRate::eVertex};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr static eastl::array<vk::VertexInputAttributeDescription, 2>
|
|
||||||
GetAttributes(const u32 binding)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
vk::VertexInputAttributeDescription{
|
|
||||||
.location = 0,
|
|
||||||
.binding = binding,
|
|
||||||
.format = vk::Format::eR32G32B32Sfloat,
|
|
||||||
.offset = offsetof(Vertex, m_Position),
|
|
||||||
},
|
|
||||||
vk::VertexInputAttributeDescription{
|
|
||||||
.location = 1,
|
|
||||||
.binding = binding,
|
|
||||||
.format = vk::Format::eR32G32Sfloat,
|
|
||||||
.offset = offsetof(Vertex, m_TexCoord0),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Camera
|
struct Camera
|
||||||
|
|
@ -127,7 +106,8 @@ main(int, char **)
|
||||||
|
|
||||||
Features enabledDeviceFeatures = {
|
Features enabledDeviceFeatures = {
|
||||||
.m_Vulkan10Features = {.samplerAnisotropy = true},
|
.m_Vulkan10Features = {.samplerAnisotropy = true},
|
||||||
.m_Vulkan13Features = {.dynamicRendering = true},
|
.m_Vulkan12Features = {.bufferDeviceAddress = true},
|
||||||
|
.m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = true},
|
||||||
};
|
};
|
||||||
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
|
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
|
||||||
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
|
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
|
||||||
|
|
@ -135,6 +115,9 @@ main(int, char **)
|
||||||
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
|
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
|
||||||
Pipeline pipeline = CreatePipeline(&device, &swapchain);
|
Pipeline pipeline = CreatePipeline(&device, &swapchain);
|
||||||
|
|
||||||
|
systems::BufferManager bufferManager{&device, 12};
|
||||||
|
systems::ImageManager imageManager{&device, 12};
|
||||||
|
|
||||||
Camera camera = {
|
Camera camera = {
|
||||||
.m_Model = {1.0f},
|
.m_Model = {1.0f},
|
||||||
.m_View = glm::lookAt(vec3(0.0f, 2.0f, 2.0f), vec3(0.0f), vec3(0.0f, 1.0f, 0.0f)),
|
.m_View = glm::lookAt(vec3(0.0f, 2.0f, 2.0f), vec3(0.0f), vec3(0.0f, 1.0f, 0.0f)),
|
||||||
|
|
@ -155,6 +138,10 @@ main(int, char **)
|
||||||
.type = vk::DescriptorType::eCombinedImageSampler,
|
.type = vk::DescriptorType::eCombinedImageSampler,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
},
|
},
|
||||||
|
vk::DescriptorPoolSize{
|
||||||
|
.type = vk::DescriptorType::eStorageBuffer,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
|
vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
|
||||||
.maxSets = 1, .poolSizeCount = Cast<u32>(poolSizes.size()), .pPoolSizes = poolSizes.data()};
|
.maxSets = 1, .poolSizeCount = Cast<u32>(poolSizes.size()), .pPoolSizes = poolSizes.data()};
|
||||||
|
|
@ -235,24 +222,32 @@ main(int, char **)
|
||||||
assert(loaded);
|
assert(loaded);
|
||||||
INFO("Image {}x{} : {} channels", imageFile.m_Width, imageFile.m_Height, imageFile.m_NumChannels);
|
INFO("Image {}x{} : {} channels", imageFile.m_Width, imageFile.m_Height, imageFile.m_NumChannels);
|
||||||
|
|
||||||
VertexBuffer vbo;
|
auto vbo = bufferManager.CreateStorageBuffer(vertices.size() * sizeof vertices[0], "Vertex Buffer").ToPointer();
|
||||||
Texture crate;
|
auto crate = imageManager
|
||||||
vbo.Init(&device, vertices.size() * sizeof vertices[0], "VBO");
|
.CreateTexture2D({
|
||||||
crate.Init(&device, {imageFile.m_Width, imageFile.m_Height}, vk::Format::eR8G8B8A8Srgb, false, "Crate Texture");
|
.m_Format = vk::Format::eR8G8B8A8Srgb,
|
||||||
|
.m_Extent = {imageFile.m_Width, imageFile.m_Height},
|
||||||
|
.m_Name = "Crate Texture",
|
||||||
|
})
|
||||||
|
.ToPointer();
|
||||||
|
vbo->Write(&device, 0, vertices.size() * sizeof vertices[0], vertices.data());
|
||||||
|
|
||||||
{
|
{
|
||||||
StagingBuffer vertexStaging, imageStaging;
|
StagingBuffer imageStaging;
|
||||||
vertexStaging.Init(&device, vertices.size() * sizeof vertices[0], "Vertex Staging");
|
|
||||||
vertexStaging.Write(&device, 0, vertices.size() * sizeof vertices[0], vertices.data());
|
|
||||||
|
|
||||||
imageStaging.Init(&device, imageFile.GetSize(), "Image Staging");
|
imageStaging.Init(&device, imageFile.GetSize(), "Image Staging");
|
||||||
imageStaging.Write(&device, 0, imageFile.GetSize(), imageFile.m_Data);
|
imageStaging.Write(&device, 0, imageFile.GetSize(), imageFile.m_Data);
|
||||||
|
|
||||||
vk::ImageMemoryBarrier imageReadyToWrite = {
|
vk::ImageMemoryBarrier2 imageReadyToWrite = {
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eNone,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
.oldLayout = vk::ImageLayout::eUndefined,
|
.oldLayout = vk::ImageLayout::eUndefined,
|
||||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.image = crate.m_Image,
|
.image = crate->m_Image,
|
||||||
.subresourceRange =
|
.subresourceRange =
|
||||||
{
|
{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
|
@ -262,13 +257,21 @@ main(int, char **)
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
vk::DependencyInfo imageReadyToWriteDependency = {
|
||||||
|
.imageMemoryBarrierCount = 1,
|
||||||
|
.pImageMemoryBarriers = &imageReadyToWrite,
|
||||||
|
};
|
||||||
|
|
||||||
vk::ImageMemoryBarrier imageReadyToRead = {
|
vk::ImageMemoryBarrier2 imageReadyToRead = {
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eFragmentShader,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eShaderRead,
|
||||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.image = crate.m_Image,
|
.image = crate->m_Image,
|
||||||
.subresourceRange =
|
.subresourceRange =
|
||||||
{
|
{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
|
@ -278,6 +281,10 @@ main(int, char **)
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
vk::DependencyInfo imageReadyToReadDependency = {
|
||||||
|
.imageMemoryBarrierCount = 1,
|
||||||
|
.pImageMemoryBarriers = &imageReadyToRead,
|
||||||
|
};
|
||||||
|
|
||||||
vk::Fence fence;
|
vk::Fence fence;
|
||||||
vk::FenceCreateInfo fenceCreateInfo = {};
|
vk::FenceCreateInfo fenceCreateInfo = {};
|
||||||
|
|
@ -285,11 +292,8 @@ main(int, char **)
|
||||||
|
|
||||||
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
||||||
AbortIfFailed(copyBuffer.begin(&beginInfo));
|
AbortIfFailed(copyBuffer.begin(&beginInfo));
|
||||||
copyBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eTransfer, {}, 0,
|
|
||||||
nullptr, 0, nullptr, 1, &imageReadyToWrite);
|
|
||||||
|
|
||||||
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = vertexStaging.GetSize()};
|
copyBuffer.pipelineBarrier2(&imageReadyToWriteDependency);
|
||||||
copyBuffer.copyBuffer(vertexStaging.m_Buffer, vbo.m_Buffer, 1, &bufferCopy);
|
|
||||||
|
|
||||||
vk::BufferImageCopy imageCopy = {
|
vk::BufferImageCopy imageCopy = {
|
||||||
.bufferOffset = 0,
|
.bufferOffset = 0,
|
||||||
|
|
@ -305,11 +309,10 @@ main(int, char **)
|
||||||
.imageOffset = {},
|
.imageOffset = {},
|
||||||
.imageExtent = {imageFile.m_Width, imageFile.m_Height, 1},
|
.imageExtent = {imageFile.m_Width, imageFile.m_Height, 1},
|
||||||
};
|
};
|
||||||
copyBuffer.copyBufferToImage(imageStaging.m_Buffer, crate.m_Image, vk::ImageLayout::eTransferDstOptimal, 1,
|
copyBuffer.copyBufferToImage(imageStaging.m_Buffer, crate->m_Image, vk::ImageLayout::eTransferDstOptimal, 1,
|
||||||
&imageCopy);
|
&imageCopy);
|
||||||
|
|
||||||
copyBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {},
|
copyBuffer.pipelineBarrier2(&imageReadyToReadDependency);
|
||||||
0, nullptr, 0, nullptr, 1, &imageReadyToRead);
|
|
||||||
|
|
||||||
AbortIfFailed(copyBuffer.end());
|
AbortIfFailed(copyBuffer.end());
|
||||||
|
|
||||||
|
|
@ -327,7 +330,6 @@ main(int, char **)
|
||||||
AbortIfFailedM(device.m_Device.resetCommandPool(copyPool, {}), "Couldn't reset command pool.");
|
AbortIfFailedM(device.m_Device.resetCommandPool(copyPool, {}), "Couldn't reset command pool.");
|
||||||
|
|
||||||
device.m_Device.destroy(fence, nullptr);
|
device.m_Device.destroy(fence, nullptr);
|
||||||
vertexStaging.Destroy(&device);
|
|
||||||
imageStaging.Destroy(&device);
|
imageStaging.Destroy(&device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -351,19 +353,23 @@ main(int, char **)
|
||||||
AbortIfFailed(device.m_Device.createSampler(&samplerCreateInfo, nullptr, &sampler));
|
AbortIfFailed(device.m_Device.createSampler(&samplerCreateInfo, nullptr, &sampler));
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformBuffer ubo;
|
auto ubo = bufferManager.CreateUniformBuffer(sizeof camera, "Camera UBO").ToPointer();
|
||||||
ubo.Init(&device, sizeof camera, "Camera UBO");
|
ubo->Write(&device, 0, sizeof camera, &camera);
|
||||||
ubo.Write(&device, 0, sizeof camera, &camera);
|
|
||||||
vk::DescriptorBufferInfo descriptorBufferInfo = {
|
vk::DescriptorBufferInfo descriptorBufferInfo = {
|
||||||
.buffer = ubo.m_Buffer,
|
.buffer = ubo->m_Buffer,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.range = ubo.GetSize(),
|
.range = ubo->GetSize(),
|
||||||
};
|
};
|
||||||
vk::DescriptorImageInfo descriptorImageInfo = {
|
vk::DescriptorImageInfo descriptorImageInfo = {
|
||||||
.sampler = sampler,
|
.sampler = sampler,
|
||||||
.imageView = crate.m_View,
|
.imageView = crate->m_View,
|
||||||
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
};
|
};
|
||||||
|
vk::DescriptorBufferInfo descriptorStorageBufferInfo = {
|
||||||
|
.buffer = vbo->m_Buffer,
|
||||||
|
.offset = 0,
|
||||||
|
.range = vbo->GetSize(),
|
||||||
|
};
|
||||||
eastl::array writeDescriptors = {
|
eastl::array writeDescriptors = {
|
||||||
vk::WriteDescriptorSet{
|
vk::WriteDescriptorSet{
|
||||||
.dstSet = descriptorSet,
|
.dstSet = descriptorSet,
|
||||||
|
|
@ -381,6 +387,14 @@ main(int, char **)
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
.pImageInfo = &descriptorImageInfo,
|
.pImageInfo = &descriptorImageInfo,
|
||||||
},
|
},
|
||||||
|
vk::WriteDescriptorSet{
|
||||||
|
.dstSet = descriptorSet,
|
||||||
|
.dstBinding = 2,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||||
|
.pBufferInfo = &descriptorStorageBufferInfo,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
device.m_Device.updateDescriptorSets(Cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
|
device.m_Device.updateDescriptorSets(Cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
|
||||||
|
|
||||||
|
|
@ -414,35 +428,56 @@ main(int, char **)
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
};
|
};
|
||||||
vk::ImageMemoryBarrier topOfThePipeBarrier = {
|
vk::ImageMemoryBarrier2 topOfThePipeBarrier = {
|
||||||
|
// For Color Attachment output ref:
|
||||||
|
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7193#issuecomment-1875960974
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eNone,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
||||||
.oldLayout = vk::ImageLayout::eUndefined,
|
.oldLayout = vk::ImageLayout::eUndefined,
|
||||||
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.subresourceRange = subresourceRange,
|
.subresourceRange = subresourceRange,
|
||||||
};
|
};
|
||||||
vk::ImageMemoryBarrier renderToPresentBarrier = {
|
vk::DependencyInfo topOfThePipeDependency = {
|
||||||
|
.imageMemoryBarrierCount = 1,
|
||||||
|
.pImageMemoryBarriers = &topOfThePipeBarrier,
|
||||||
|
};
|
||||||
|
vk::ImageMemoryBarrier2 renderToPresentBarrier = {
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eBottomOfPipe,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eNone,
|
||||||
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.subresourceRange = subresourceRange,
|
.subresourceRange = subresourceRange,
|
||||||
};
|
};
|
||||||
|
vk::DependencyInfo renderToPresentDependency = {
|
||||||
|
.imageMemoryBarrierCount = 1,
|
||||||
|
.pImageMemoryBarriers = &renderToPresentBarrier,
|
||||||
|
};
|
||||||
|
|
||||||
FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT};
|
FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT};
|
||||||
eastl::fixed_vector<DepthImage, MAX_FRAMES_IN_FLIGHT> depthImages(frameManager.m_FramesInFlight);
|
eastl::fixed_vector<Ref<Image>, MAX_FRAMES_IN_FLIGHT> depthImages;
|
||||||
for (auto &depthImage : depthImages)
|
|
||||||
{
|
|
||||||
depthImage.Init(&device, swapchain.m_Extent, "Depth");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto recreateDepthBuffers = [&device, &depthImages](vk::Extent2D extent) {
|
auto initDepthImages = [&imageManager, &depthImages, &frameManager] (const vk::Extent2D extent) {
|
||||||
for (auto &depthImage : depthImages)
|
for (u32 i = 0; i < frameManager.m_FramesInFlight; ++i)
|
||||||
{
|
{
|
||||||
depthImage.Destroy(&device);
|
depthImages.push_back(
|
||||||
depthImage.Init(&device, extent, "Depth");
|
imageManager.CreateDepthStencilImage({.m_Extent = extent, .m_Name = "Depth"}).ToPointer());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
initDepthImages(swapchain.m_Extent);
|
||||||
|
|
||||||
|
auto recreateDepthBuffers = [&depthImages, &initDepthImages](const vk::Extent2D extent) {
|
||||||
|
depthImages.clear();
|
||||||
|
initDepthImages(extent);
|
||||||
|
};
|
||||||
swapchain.RegisterResizeCallback(recreateDepthBuffers);
|
swapchain.RegisterResizeCallback(recreateDepthBuffers);
|
||||||
|
|
||||||
Time::Init();
|
Time::Init();
|
||||||
|
|
@ -453,7 +488,7 @@ main(int, char **)
|
||||||
Time::Update();
|
Time::Update();
|
||||||
|
|
||||||
camera.m_Model *= rotate(mat4{1.0f}, Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f));
|
camera.m_Model *= rotate(mat4{1.0f}, Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f));
|
||||||
ubo.Write(&device, 0, sizeof camera, &camera);
|
ubo->Write(&device, 0, sizeof camera, &camera);
|
||||||
|
|
||||||
Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &surface, window.GetSize());
|
Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &surface, window.GetSize());
|
||||||
|
|
||||||
|
|
@ -461,7 +496,7 @@ main(int, char **)
|
||||||
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
|
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
|
||||||
vk::Image currentImage = swapchain.m_Images[imageIndex];
|
vk::Image currentImage = swapchain.m_Images[imageIndex];
|
||||||
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
|
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
|
||||||
vk::ImageView currentDepthImageView = depthImages[currentFrame->m_FrameIdx].m_View;
|
vk::ImageView currentDepthImageView = depthImages[currentFrame->m_FrameIdx]->m_View;
|
||||||
|
|
||||||
topOfThePipeBarrier.image = currentImage;
|
topOfThePipeBarrier.image = currentImage;
|
||||||
renderToPresentBarrier.image = currentImage;
|
renderToPresentBarrier.image = currentImage;
|
||||||
|
|
@ -469,8 +504,7 @@ main(int, char **)
|
||||||
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
||||||
AbortIfFailed(cmd.begin(&beginInfo));
|
AbortIfFailed(cmd.begin(&beginInfo));
|
||||||
|
|
||||||
cmd.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
cmd.pipelineBarrier2(&topOfThePipeDependency);
|
||||||
{}, 0, nullptr, 0, nullptr, 1, &topOfThePipeBarrier);
|
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
eastl::array attachmentInfos = {
|
eastl::array attachmentInfos = {
|
||||||
|
|
@ -480,7 +514,7 @@ main(int, char **)
|
||||||
.resolveMode = vk::ResolveModeFlagBits::eNone,
|
.resolveMode = vk::ResolveModeFlagBits::eNone,
|
||||||
.loadOp = vk::AttachmentLoadOp::eClear,
|
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
.clearValue = vk::ClearColorValue{0.0f, 0.0f, 0.0f, 1.0f},
|
.clearValue = vk::ClearColorValue{0.0f, 0.0f, 0.0f, 0.0f},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -507,14 +541,11 @@ main(int, char **)
|
||||||
cmd.setScissor(0, 1, &scissor);
|
cmd.setScissor(0, 1, &scissor);
|
||||||
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
|
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
|
||||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1, &descriptorSet, 0, nullptr);
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1, &descriptorSet, 0, nullptr);
|
||||||
usize offsets = 0;
|
|
||||||
cmd.bindVertexBuffers(0, 1, &vbo.m_Buffer, &offsets);
|
|
||||||
cmd.draw(Cast<u32>(vertices.size()), 1, 0, 0);
|
cmd.draw(Cast<u32>(vertices.size()), 1, 0, 0);
|
||||||
|
|
||||||
cmd.endRendering();
|
cmd.endRendering();
|
||||||
|
|
||||||
cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eBottomOfPipe,
|
cmd.pipelineBarrier2(&renderToPresentDependency);
|
||||||
{}, 0, nullptr, 0, nullptr, 1, &renderToPresentBarrier);
|
|
||||||
|
|
||||||
AbortIfFailed(cmd.end());
|
AbortIfFailed(cmd.end());
|
||||||
|
|
||||||
|
|
@ -534,17 +565,9 @@ main(int, char **)
|
||||||
}
|
}
|
||||||
|
|
||||||
device.WaitIdle();
|
device.WaitIdle();
|
||||||
|
|
||||||
for (auto &depthImage : depthImages)
|
|
||||||
{
|
|
||||||
depthImage.Destroy(&device);
|
|
||||||
}
|
|
||||||
device.m_Device.destroy(sampler, nullptr);
|
device.m_Device.destroy(sampler, nullptr);
|
||||||
ubo.Destroy(&device);
|
|
||||||
device.m_Device.destroy(descriptorPool, nullptr);
|
device.m_Device.destroy(descriptorPool, nullptr);
|
||||||
device.m_Device.destroy(copyPool, nullptr);
|
device.m_Device.destroy(copyPool, nullptr);
|
||||||
crate.Destroy(&device);
|
|
||||||
vbo.Destroy(&device);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -582,6 +605,12 @@ CreatePipeline(const Device *device, const Swapchain *swapchain)
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||||
},
|
},
|
||||||
|
vk::DescriptorSetLayoutBinding{
|
||||||
|
.binding = 2,
|
||||||
|
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eVertex,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
.bindingCount = Cast<u32>(descriptorSetLayoutBinding.size()),
|
.bindingCount = Cast<u32>(descriptorSetLayoutBinding.size()),
|
||||||
|
|
@ -601,15 +630,7 @@ CreatePipeline(const Device *device, const Swapchain *swapchain)
|
||||||
AbortIfFailed(device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
AbortIfFailed(device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||||
device->SetName(pipelineLayout, "Box Layout");
|
device->SetName(pipelineLayout, "Box Layout");
|
||||||
|
|
||||||
vk::VertexInputBindingDescription inputBindingDescription = Vertex::GetBinding(0);
|
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {};
|
||||||
auto inputAttributeDescription = Vertex::GetAttributes(0);
|
|
||||||
|
|
||||||
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
|
|
||||||
.vertexBindingDescriptionCount = 1,
|
|
||||||
.pVertexBindingDescriptions = &inputBindingDescription,
|
|
||||||
.vertexAttributeDescriptionCount = Cast<u32>(inputAttributeDescription.size()),
|
|
||||||
.pVertexAttributeDescriptions = inputAttributeDescription.data(),
|
|
||||||
};
|
|
||||||
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
|
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
|
||||||
.topology = vk::PrimitiveTopology::eTriangleList,
|
.topology = vk::PrimitiveTopology::eTriangleList,
|
||||||
.primitiveRestartEnable = false,
|
.primitiveRestartEnable = false,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
struct FS_Input {
|
||||||
|
float2 UV0 : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FS_Output
|
||||||
|
{
|
||||||
|
float4 ColorTarget : SV_Target0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[vk::binding(1, 0)]] Texture2D<float4> Texture;
|
||||||
|
[[vk::binding(1, 0)]] SamplerState Sampler;
|
||||||
|
|
||||||
|
FS_Output main(FS_Input StageInput) {
|
||||||
|
FS_Output output;
|
||||||
|
|
||||||
|
output.ColorTarget = float4(Texture.Sample(Sampler, StageInput.UV0).rgb, 1.0);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
struct VS_Input
|
||||||
|
{
|
||||||
|
uint VertexIndex : SV_VertexID;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VS_Output
|
||||||
|
{
|
||||||
|
float2 UV0 : TEXCOORD0;
|
||||||
|
float4 VertexPosition : SV_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CameraData {
|
||||||
|
float4x4 Model;
|
||||||
|
float4x4 View;
|
||||||
|
float4x4 Projection;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexData {
|
||||||
|
float4 Position;
|
||||||
|
float2 UV0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[vk::binding(0, 0)]] ConstantBuffer<CameraData> Camera;
|
||||||
|
[[vk::binding(2, 0)]] StructuredBuffer<VertexData> Vertices;
|
||||||
|
|
||||||
|
VS_Output main(VS_Input StageInput) {
|
||||||
|
VS_Output output;
|
||||||
|
|
||||||
|
output.UV0 = Vertices[StageInput.VertexIndex].UV0;
|
||||||
|
|
||||||
|
float4 position = Vertices[StageInput.VertexIndex].Position;
|
||||||
|
|
||||||
|
output.VertexPosition = mul(Camera.Projection, mul(Camera.View, mul(Camera.Model, position)));
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue