Texture bindless works!
This commit is contained in:
parent
c7ea45bce7
commit
6c15f599aa
|
|
@ -11,11 +11,11 @@
|
||||||
void
|
void
|
||||||
Buffer::Destroy(const Device *device)
|
Buffer::Destroy(const Device *device)
|
||||||
{
|
{
|
||||||
if (!m_Buffer)
|
if (!IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vmaDestroyBuffer(device->m_Allocator, m_Buffer, m_Allocation);
|
vmaDestroyBuffer(device->m_Allocator, m_Buffer, m_Allocation);
|
||||||
m_Buffer = nullptr;
|
m_Size &= ~VALID_BUFFER_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -41,24 +41,21 @@ Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUs
|
||||||
&allocationCreateInfo, &buffer, &allocation, &allocationInfo));
|
&allocationCreateInfo, &buffer, &allocation, &allocationInfo));
|
||||||
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
|
||||||
|
|
||||||
m_Buffer = buffer;
|
|
||||||
m_Size = size & SIZE_MASK;
|
|
||||||
m_Allocation = allocation;
|
|
||||||
m_Mapped = allocationInfo.pMappedData;
|
|
||||||
|
|
||||||
vk::MemoryPropertyFlags memoryPropertyFlags;
|
vk::MemoryPropertyFlags memoryPropertyFlags;
|
||||||
vmaGetAllocationMemoryProperties(device->m_Allocator, allocation,
|
vmaGetAllocationMemoryProperties(device->m_Allocator, allocation,
|
||||||
Recast<VkMemoryPropertyFlags *>(&memoryPropertyFlags));
|
Recast<VkMemoryPropertyFlags *>(&memoryPropertyFlags));
|
||||||
if (memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)
|
bool hostAccessible = Cast<bool>(memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
{
|
|
||||||
m_Size |= HOST_ACCESSIBLE_BIT;
|
m_Buffer = buffer;
|
||||||
}
|
m_Size = size | VALID_BUFFER_BIT | (hostAccessible ? HOST_ACCESSIBLE_BIT : 0);
|
||||||
|
m_Allocation = allocation;
|
||||||
|
m_Mapped = allocationInfo.pMappedData;
|
||||||
|
|
||||||
device->SetName(m_Buffer, name);
|
device->SetName(m_Buffer, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Buffer::Write(const Device *device, usize offset, usize size, void *data)
|
Buffer::Write(const Device *device, usize offset, usize size, const void *data)
|
||||||
{
|
{
|
||||||
assert(IsHostVisible());
|
assert(IsHostVisible());
|
||||||
|
|
||||||
|
|
@ -93,6 +90,15 @@ UniformBuffer::Init(const Device *device, const usize size, const cstr name)
|
||||||
VMA_MEMORY_USAGE_AUTO, name);
|
VMA_MEMORY_USAGE_AUTO, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UniformStorageBuffer::Init(const Device *device, usize size, cstr name)
|
||||||
|
{
|
||||||
|
Allocate(device, size, vk::BufferUsageFlagBits::eStorageBuffer,
|
||||||
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VertexBuffer::Init(const Device *device, usize size, cstr name)
|
VertexBuffer::Init(const Device *device, usize size, cstr name)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,19 +17,23 @@ struct Buffer
|
||||||
|
|
||||||
[[nodiscard]] usize GetSize() const;
|
[[nodiscard]] usize GetSize() const;
|
||||||
[[nodiscard]] bool IsHostVisible() const;
|
[[nodiscard]] bool IsHostVisible() const;
|
||||||
|
[[nodiscard]] bool IsValid() const;
|
||||||
[[nodiscard]] bool IsMapped() const;
|
[[nodiscard]] bool IsMapped() const;
|
||||||
|
|
||||||
void Destroy(const Device *device);
|
void Destroy(const Device *device);
|
||||||
void Write(const Device *device, usize offset, usize size, void *data);
|
void Write(const Device *device, usize offset, usize size, const void *data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUsage,
|
void Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUsage,
|
||||||
VmaAllocationCreateFlags allocationFlags, VmaMemoryUsage memoryUsage, cstr name);
|
VmaAllocationCreateFlags allocationFlags, VmaMemoryUsage memoryUsage, cstr name);
|
||||||
|
|
||||||
|
// Buffer size is used intrusively by the Render Resource Manager
|
||||||
|
// If the buffer is Invalid, the remaining data in Buffer is used for other tasks.
|
||||||
usize m_Size = 0;
|
usize m_Size = 0;
|
||||||
|
|
||||||
constexpr static usize HOST_ACCESSIBLE_BIT = 1llu << 63;
|
constexpr static usize VALID_BUFFER_BIT = Cast<usize>(1llu << 63);
|
||||||
constexpr static usize SIZE_MASK = ~HOST_ACCESSIBLE_BIT;
|
constexpr static usize HOST_ACCESSIBLE_BIT = 1llu << 62;
|
||||||
|
constexpr static usize SIZE_MASK = ~(VALID_BUFFER_BIT | HOST_ACCESSIBLE_BIT);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UniformBuffer : Buffer
|
struct UniformBuffer : Buffer
|
||||||
|
|
@ -37,6 +41,11 @@ struct UniformBuffer : Buffer
|
||||||
void Init(const Device *device, usize size, cstr name = nullptr);
|
void Init(const Device *device, usize size, cstr name = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UniformStorageBuffer : Buffer
|
||||||
|
{
|
||||||
|
void Init(const Device *device, usize size, cstr name = nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
struct VertexBuffer : Buffer
|
struct VertexBuffer : Buffer
|
||||||
{
|
{
|
||||||
void Init(const Device *device, usize size, cstr name = nullptr);
|
void Init(const Device *device, usize size, cstr name = nullptr);
|
||||||
|
|
@ -60,6 +69,12 @@ Buffer::IsHostVisible() const
|
||||||
return m_Size & HOST_ACCESSIBLE_BIT;
|
return m_Size & HOST_ACCESSIBLE_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
Buffer::IsValid() const
|
||||||
|
{
|
||||||
|
return m_Size & VALID_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
Buffer::IsMapped() const
|
Buffer::IsMapped() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ using f128 = long double;
|
||||||
using b8 = bool;
|
using b8 = bool;
|
||||||
using b32 = u32;
|
using b32 = u32;
|
||||||
using usize = size_t;
|
using usize = size_t;
|
||||||
using p64 = intptr_t;
|
using uptr = uintptr_t;
|
||||||
using cstr = const char *;
|
using cstr = const char *;
|
||||||
|
|
||||||
namespace ansi_color
|
namespace ansi_color
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ HashCombine(const usize hash0, const usize hash1)
|
||||||
|
|
||||||
struct Time
|
struct Time
|
||||||
{
|
{
|
||||||
static constexpr f64 cMaxDelta = 0.1;
|
static constexpr f64 MAX_DELTA = 0.1;
|
||||||
|
|
||||||
inline static f64 m_Elapsed{Qnan<f64>};
|
inline static f64 m_Elapsed{Qnan<f64>};
|
||||||
inline static f64 m_Delta{Qnan<f64>};
|
inline static f64 m_Delta{Qnan<f64>};
|
||||||
|
|
@ -93,7 +93,7 @@ struct Time
|
||||||
{
|
{
|
||||||
ERROR_IF(std::isnan(m_Elapsed), "Time not init.");
|
ERROR_IF(std::isnan(m_Elapsed), "Time not init.");
|
||||||
const auto newElapsed = glfwGetTime();
|
const auto newElapsed = glfwGetTime();
|
||||||
m_Delta = std::clamp(newElapsed - m_Elapsed, 0.0, cMaxDelta);
|
m_Delta = std::clamp(newElapsed - m_Elapsed, 0.0, MAX_DELTA);
|
||||||
m_Elapsed = newElapsed;
|
m_Elapsed = newElapsed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,10 @@
|
||||||
void
|
void
|
||||||
Image::Destroy(const Device *device)
|
Image::Destroy(const Device *device)
|
||||||
{
|
{
|
||||||
if (!m_Image)
|
if (!IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
device->m_Device.destroy(m_View, nullptr);
|
||||||
vmaDestroyImage(device->m_Allocator, m_Image, m_Allocation);
|
vmaDestroyImage(device->m_Allocator, m_Image, m_Allocation);
|
||||||
m_Image = nullptr;
|
m_Image = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -20,10 +21,12 @@ Image::Destroy(const Device *device)
|
||||||
void
|
void
|
||||||
Texture::Init(const Device *device, const vk::Extent2D extent, const bool isMipmapped, const cstr name)
|
Texture::Init(const Device *device, const vk::Extent2D extent, const bool isMipmapped, const cstr name)
|
||||||
{
|
{
|
||||||
|
constexpr vk::Format imageFormat = vk::Format::eR8G8B8A8Srgb;
|
||||||
|
|
||||||
const u32 mipLevels = isMipmapped ? 1 + Cast<u32>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
|
const u32 mipLevels = isMipmapped ? 1 + Cast<u32>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
|
||||||
vk::ImageCreateInfo imageCreateInfo = {
|
vk::ImageCreateInfo imageCreateInfo = {
|
||||||
.imageType = vk::ImageType::e2D,
|
.imageType = vk::ImageType::e2D,
|
||||||
.format = vk::Format::eR8G8B8A8Srgb,
|
.format = imageFormat,
|
||||||
.extent = {.width = extent.width, .height = extent.height, .depth = 1},
|
.extent = {.width = extent.width, .height = extent.height, .depth = 1},
|
||||||
.mipLevels = mipLevels,
|
.mipLevels = mipLevels,
|
||||||
.arrayLayers = 1,
|
.arrayLayers = 1,
|
||||||
|
|
@ -42,9 +45,28 @@ Texture::Init(const Device *device, const vk::Extent2D extent, const bool isMipm
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
&allocationCreateInfo, &image, &allocation, nullptr));
|
&allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
|
vk::ImageView view;
|
||||||
|
vk::ImageViewCreateInfo imageViewCreateInfo = {
|
||||||
|
.image = image,
|
||||||
|
.viewType = vk::ImageViewType::e2D,
|
||||||
|
.format = imageFormat,
|
||||||
|
.components = {},
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = mipLevels,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
|
||||||
|
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
m_Image = image;
|
m_Image = image;
|
||||||
|
m_View = view;
|
||||||
m_Allocation = allocation;
|
m_Allocation = allocation;
|
||||||
m_Extent = {extent.width, extent.height, 1};
|
m_Extent = {extent.width, extent.height, 1};
|
||||||
|
|
||||||
|
|
@ -54,9 +76,10 @@ Texture::Init(const Device *device, const vk::Extent2D extent, const bool isMipm
|
||||||
void
|
void
|
||||||
DepthImage::Init(const Device *device, vk::Extent2D extent, cstr name)
|
DepthImage::Init(const Device *device, vk::Extent2D extent, cstr name)
|
||||||
{
|
{
|
||||||
|
constexpr vk::Format imageFormat = vk::Format::eD32Sfloat;
|
||||||
vk::ImageCreateInfo imageCreateInfo = {
|
vk::ImageCreateInfo imageCreateInfo = {
|
||||||
.imageType = vk::ImageType::e2D,
|
.imageType = vk::ImageType::e2D,
|
||||||
.format = vk::Format::eD32Sfloat,
|
.format = imageFormat,
|
||||||
.extent = {.width = extent.width, .height = extent.height, .depth = 1},
|
.extent = {.width = extent.width, .height = extent.height, .depth = 1},
|
||||||
.mipLevels = 1,
|
.mipLevels = 1,
|
||||||
.arrayLayers = 1,
|
.arrayLayers = 1,
|
||||||
|
|
@ -75,9 +98,28 @@ DepthImage::Init(const Device *device, vk::Extent2D extent, cstr name)
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
&allocationCreateInfo, &image, &allocation, nullptr));
|
&allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result);
|
||||||
|
|
||||||
|
vk::ImageView view;
|
||||||
|
vk::ImageViewCreateInfo imageViewCreateInfo = {
|
||||||
|
.image = image,
|
||||||
|
.viewType = vk::ImageViewType::e2D,
|
||||||
|
.format = imageFormat,
|
||||||
|
.components = {},
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eDepth,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
|
||||||
|
ERROR_IF(Failed(result), "Could not create depth image view {}. Cause: {}", name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
m_Image = image;
|
m_Image = image;
|
||||||
|
m_View = view;
|
||||||
m_Allocation = allocation;
|
m_Allocation = allocation;
|
||||||
m_Extent = {extent.width, extent.height, 1};
|
m_Extent = {extent.width, extent.height, 1};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,11 @@ struct Device;
|
||||||
struct Image
|
struct Image
|
||||||
{
|
{
|
||||||
vk::Image m_Image = nullptr;
|
vk::Image m_Image = nullptr;
|
||||||
|
vk::ImageView m_View = nullptr;
|
||||||
VmaAllocation m_Allocation = nullptr;
|
VmaAllocation m_Allocation = nullptr;
|
||||||
vk::Extent3D m_Extent;
|
vk::Extent3D m_Extent;
|
||||||
usize m_Size = 0;
|
|
||||||
|
[[nodiscard]] bool IsValid() const;
|
||||||
|
|
||||||
void Destroy(const Device *device);
|
void Destroy(const Device *device);
|
||||||
};
|
};
|
||||||
|
|
@ -28,3 +30,9 @@ struct DepthImage : Image
|
||||||
{
|
{
|
||||||
void Init(const Device *device, vk::Extent2D extent, cstr name = nullptr);
|
void Init(const Device *device, vk::Extent2D extent, cstr name = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
Image::IsValid() const
|
||||||
|
{
|
||||||
|
return m_Image;
|
||||||
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ ImageFile::Load(cstr fileName)
|
||||||
usize
|
usize
|
||||||
ImageFile::GetSize() const
|
ImageFile::GetSize() const
|
||||||
{
|
{
|
||||||
return m_Width * m_Height * m_NumChannels;
|
return Cast<usize>(m_Width) * m_Height * m_NumChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageFile::~ImageFile()
|
ImageFile::~ImageFile()
|
||||||
|
|
@ -330,30 +330,8 @@ main(int, char **)
|
||||||
imageStaging.Destroy(&device);
|
imageStaging.Destroy(&device);
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::ImageView imageView;
|
|
||||||
vk::Sampler sampler;
|
vk::Sampler sampler;
|
||||||
{
|
{
|
||||||
vk::ImageViewCreateInfo imageViewCreateInfo = {
|
|
||||||
.image = crate.m_Image,
|
|
||||||
.viewType = vk::ImageViewType::e2D,
|
|
||||||
.format = vk::Format::eR8G8B8A8Srgb,
|
|
||||||
.components =
|
|
||||||
vk::ComponentMapping{
|
|
||||||
.r = vk::ComponentSwizzle::eIdentity,
|
|
||||||
.g = vk::ComponentSwizzle::eIdentity,
|
|
||||||
.b = vk::ComponentSwizzle::eIdentity,
|
|
||||||
.a = vk::ComponentSwizzle::eIdentity,
|
|
||||||
},
|
|
||||||
.subresourceRange =
|
|
||||||
{
|
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
AbortIfFailed(device.m_Device.createImageView(&imageViewCreateInfo, nullptr, &imageView));
|
|
||||||
vk::SamplerCreateInfo samplerCreateInfo = {
|
vk::SamplerCreateInfo samplerCreateInfo = {
|
||||||
.magFilter = vk::Filter::eLinear,
|
.magFilter = vk::Filter::eLinear,
|
||||||
.minFilter = vk::Filter::eLinear,
|
.minFilter = vk::Filter::eLinear,
|
||||||
|
|
@ -382,7 +360,7 @@ main(int, char **)
|
||||||
};
|
};
|
||||||
vk::DescriptorImageInfo descriptorImageInfo = {
|
vk::DescriptorImageInfo descriptorImageInfo = {
|
||||||
.sampler = sampler,
|
.sampler = sampler,
|
||||||
.imageView = imageView,
|
.imageView = crate.m_View,
|
||||||
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
};
|
};
|
||||||
eastl::array writeDescriptors = {
|
eastl::array writeDescriptors = {
|
||||||
|
|
@ -452,52 +430,16 @@ main(int, char **)
|
||||||
|
|
||||||
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<DepthImage, MAX_FRAMES_IN_FLIGHT> depthImages(frameManager.m_FramesInFlight);
|
||||||
eastl::fixed_vector<vk::ImageView, MAX_FRAMES_IN_FLIGHT> depthViews(frameManager.m_FramesInFlight);
|
|
||||||
|
|
||||||
vk::ImageSubresourceRange depthSubresourceRange = {
|
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eDepth,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 index = 0;
|
|
||||||
for (auto &depthImage : depthImages)
|
for (auto &depthImage : depthImages)
|
||||||
{
|
{
|
||||||
auto name = fmt::format("Depth image {}", index);
|
depthImage.Init(&device, swapchain.m_Extent, "Depth");
|
||||||
depthImage.Init(&device, swapchain.m_Extent, name.c_str());
|
|
||||||
vk::ImageViewCreateInfo imageViewCreateInfo = {
|
|
||||||
.image = depthImage.m_Image,
|
|
||||||
.viewType = vk::ImageViewType::e2D,
|
|
||||||
.format = vk::Format::eD32Sfloat,
|
|
||||||
.components = vk::ComponentMapping{.r = vk::ComponentSwizzle::eIdentity},
|
|
||||||
.subresourceRange = depthSubresourceRange,
|
|
||||||
};
|
|
||||||
AbortIfFailed(device.m_Device.createImageView(&imageViewCreateInfo, nullptr, &depthViews[index]));
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto recreateDepthBuffers = [&device, &depthImages, &depthViews, depthSubresourceRange](vk::Extent2D extent) {
|
auto recreateDepthBuffers = [&device, &depthImages](vk::Extent2D extent) {
|
||||||
for (auto &depthView : depthViews)
|
|
||||||
{
|
|
||||||
device.m_Device.destroy(depthView, nullptr);
|
|
||||||
}
|
|
||||||
u32 index = 0;
|
|
||||||
for (auto &depthImage : depthImages)
|
for (auto &depthImage : depthImages)
|
||||||
{
|
{
|
||||||
depthImage.Destroy(&device);
|
depthImage.Destroy(&device);
|
||||||
depthImage.Init(&device, extent, "Depth");
|
depthImage.Init(&device, extent, "Depth");
|
||||||
vk::ImageViewCreateInfo imageViewCreateInfo = {
|
|
||||||
.image = depthImage.m_Image,
|
|
||||||
.viewType = vk::ImageViewType::e2D,
|
|
||||||
.format = vk::Format::eD32Sfloat,
|
|
||||||
.components = vk::ComponentMapping{.r = vk::ComponentSwizzle::eIdentity},
|
|
||||||
.subresourceRange = depthSubresourceRange,
|
|
||||||
};
|
|
||||||
AbortIfFailed(device.m_Device.createImageView(&imageViewCreateInfo, nullptr, &depthViews[index]));
|
|
||||||
++index;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
swapchain.RegisterResizeCallback(recreateDepthBuffers);
|
swapchain.RegisterResizeCallback(recreateDepthBuffers);
|
||||||
|
|
@ -518,7 +460,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 = depthViews[currentFrame->m_FrameIdx];
|
vk::ImageView currentDepthImageView = depthImages[currentFrame->m_FrameIdx].m_View;
|
||||||
|
|
||||||
topOfThePipeBarrier.image = currentImage;
|
topOfThePipeBarrier.image = currentImage;
|
||||||
renderToPresentBarrier.image = currentImage;
|
renderToPresentBarrier.image = currentImage;
|
||||||
|
|
@ -592,16 +534,11 @@ main(int, char **)
|
||||||
|
|
||||||
AbortIfFailed(device.m_Device.waitIdle());
|
AbortIfFailed(device.m_Device.waitIdle());
|
||||||
|
|
||||||
for (auto &depthView : depthViews)
|
|
||||||
{
|
|
||||||
device.m_Device.destroy(depthView, nullptr);
|
|
||||||
}
|
|
||||||
for (auto &depthImage : depthImages)
|
for (auto &depthImage : depthImages)
|
||||||
{
|
{
|
||||||
depthImage.Destroy(&device);
|
depthImage.Destroy(&device);
|
||||||
}
|
}
|
||||||
device.m_Device.destroy(sampler, nullptr);
|
device.m_Device.destroy(sampler, nullptr);
|
||||||
device.m_Device.destroy(imageView, nullptr);
|
|
||||||
ubo.Destroy(&device);
|
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);
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,4 @@ target_link_libraries(model_render PRIVATE util_helper)
|
||||||
target_include_directories(model_render PRIVATE ${TINYGLTF_INCLUDE_DIRS})
|
target_include_directories(model_render PRIVATE ${TINYGLTF_INCLUDE_DIRS})
|
||||||
|
|
||||||
add_resource_dir(model_render model)
|
add_resource_dir(model_render model)
|
||||||
|
add_resource_dir(model_render image)
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -36,11 +36,13 @@ constexpr auto MODEL_FILE = "model/Box.glb";
|
||||||
|
|
||||||
struct ImageFile
|
struct ImageFile
|
||||||
{
|
{
|
||||||
u8 *m_Data = nullptr;
|
void *m_Data = nullptr;
|
||||||
u32 m_Width = 512;
|
u32 m_Width = 0;
|
||||||
u32 m_Height = 512;
|
u32 m_Height = 0;
|
||||||
u32 m_NumChannels = 4;
|
u32 m_NumChannels = 0;
|
||||||
|
bool m_Constant = false;
|
||||||
|
|
||||||
|
bool Load(cstr fileName);
|
||||||
bool Load(vec4 color);
|
bool Load(vec4 color);
|
||||||
[[nodiscard]] usize GetSize() const;
|
[[nodiscard]] usize GetSize() const;
|
||||||
~ImageFile();
|
~ImageFile();
|
||||||
|
|
@ -102,14 +104,27 @@ main(int, char **)
|
||||||
|
|
||||||
Features enabledDeviceFeatures = {
|
Features enabledDeviceFeatures = {
|
||||||
.m_Vulkan10Features = {.samplerAnisotropy = true},
|
.m_Vulkan10Features = {.samplerAnisotropy = true},
|
||||||
.m_Vulkan12Features = {.descriptorIndexing = true},
|
.m_Vulkan12Features =
|
||||||
|
{
|
||||||
|
.descriptorIndexing = true,
|
||||||
|
.shaderSampledImageArrayNonUniformIndexing = true,
|
||||||
|
.shaderStorageBufferArrayNonUniformIndexing = true,
|
||||||
|
.shaderStorageImageArrayNonUniformIndexing = true,
|
||||||
|
.descriptorBindingUniformBufferUpdateAfterBind = true, // Not related to Bindless
|
||||||
|
.descriptorBindingSampledImageUpdateAfterBind = true,
|
||||||
|
.descriptorBindingStorageImageUpdateAfterBind = true,
|
||||||
|
.descriptorBindingStorageBufferUpdateAfterBind = true,
|
||||||
|
.descriptorBindingPartiallyBound = true,
|
||||||
|
.runtimeDescriptorArray = true,
|
||||||
|
},
|
||||||
.m_Vulkan13Features = {.dynamicRendering = true},
|
.m_Vulkan13Features = {.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"};
|
||||||
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
||||||
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
||||||
RenderResourceManager resourceManager(&device);
|
RenderResourceManager resourceManager(&device, 10);
|
||||||
|
|
||||||
Pipeline pipeline = CreatePipeline(&device, &swapchain, &resourceManager);
|
Pipeline pipeline = CreatePipeline(&device, &swapchain, &resourceManager);
|
||||||
|
|
||||||
|
|
@ -210,55 +225,97 @@ main(int, char **)
|
||||||
Vertex{.m_Position = vec3(0.5f, 0.5f, 0.5f), .m_UV0 = vec2(1.0f, 1.0f)},
|
Vertex{.m_Position = vec3(0.5f, 0.5f, 0.5f), .m_UV0 = vec2(1.0f, 1.0f)},
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageFile imageFile;
|
ImageFile crateImageFile;
|
||||||
bool loaded = imageFile.Load({0.7f, 0.4f, 0.1f, 1.0f});
|
ImageFile plainImageFile;
|
||||||
assert(loaded);
|
assert(crateImageFile.Load("image/container.jpg"));
|
||||||
INFO("Image {}x{} : {} channels", imageFile.m_Width, imageFile.m_Height, imageFile.m_NumChannels);
|
INFO("Image {}x{} : {} channels", crateImageFile.m_Width, crateImageFile.m_Height, crateImageFile.m_NumChannels);
|
||||||
|
assert(plainImageFile.Load({0.7f, 0.4f, 0.1f, 1.0f}));
|
||||||
|
|
||||||
VertexBuffer vbo;
|
VertexBuffer vbo;
|
||||||
Texture crate;
|
Texture crateTexture;
|
||||||
|
Texture plainTexture;
|
||||||
vbo.Init(&device, vertices.size() * sizeof vertices[0], "VBO");
|
vbo.Init(&device, vertices.size() * sizeof vertices[0], "VBO");
|
||||||
crate.Init(&device, {imageFile.m_Width, imageFile.m_Height}, false, "Crate Texture");
|
crateTexture.Init(&device, {crateImageFile.m_Width, crateImageFile.m_Height}, false, "Crate Texture");
|
||||||
|
plainTexture.Init(&device, {crateImageFile.m_Width, crateImageFile.m_Height}, false, "Plain Texture");
|
||||||
|
|
||||||
|
auto crateTextureId = resourceManager.Commit(&crateTexture);
|
||||||
|
auto plainTextureId = resourceManager.Commit(&plainTexture);
|
||||||
|
|
||||||
{
|
{
|
||||||
StagingBuffer vertexStaging, imageStaging;
|
StagingBuffer vertexStaging, imageStaging1, imageStaging2;
|
||||||
vertexStaging.Init(&device, vertices.size() * sizeof vertices[0], "Vertex Staging");
|
vertexStaging.Init(&device, vertices.size() * sizeof vertices[0], "Vertex Staging");
|
||||||
vertexStaging.Write(&device, 0, vertices.size() * sizeof vertices[0], vertices.data());
|
vertexStaging.Write(&device, 0, vertices.size() * sizeof vertices[0], vertices.data());
|
||||||
|
|
||||||
imageStaging.Init(&device, imageFile.GetSize(), "Image Staging");
|
imageStaging1.Init(&device, crateImageFile.GetSize(), "Image Staging 1");
|
||||||
INFO("fine {}", imageFile.GetSize());
|
imageStaging1.Write(&device, 0, crateImageFile.GetSize(), crateImageFile.m_Data);
|
||||||
imageStaging.Write(&device, 0, imageFile.GetSize(), imageFile.m_Data);
|
|
||||||
|
|
||||||
vk::ImageMemoryBarrier imageReadyToWrite = {
|
imageStaging2.Init(&device, plainImageFile.GetSize(), "Image Staging 2");
|
||||||
.oldLayout = vk::ImageLayout::eUndefined,
|
imageStaging2.Write(&device, 0, plainImageFile.GetSize(), plainImageFile.m_Data);
|
||||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
eastl::array imageReadyToWrite = {
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
vk::ImageMemoryBarrier{
|
||||||
.image = crate.m_Image,
|
.oldLayout = vk::ImageLayout::eUndefined,
|
||||||
.subresourceRange =
|
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
{
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.baseMipLevel = 0,
|
.image = crateTexture.m_Image,
|
||||||
.levelCount = 1,
|
.subresourceRange =
|
||||||
.baseArrayLayer = 0,
|
{
|
||||||
.layerCount = 1,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
},
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
vk::ImageMemoryBarrier{
|
||||||
|
.oldLayout = vk::ImageLayout::eUndefined,
|
||||||
|
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
|
.image = plainTexture.m_Image,
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::ImageMemoryBarrier imageReadyToRead = {
|
eastl::array imageReadyToRead = {
|
||||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
vk::ImageMemoryBarrier{
|
||||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.image = crate.m_Image,
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
.subresourceRange =
|
.image = crateTexture.m_Image,
|
||||||
{
|
.subresourceRange =
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
{
|
||||||
.baseMipLevel = 0,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
.levelCount = 1,
|
.baseMipLevel = 0,
|
||||||
.baseArrayLayer = 0,
|
.levelCount = 1,
|
||||||
.layerCount = 1,
|
.baseArrayLayer = 0,
|
||||||
},
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
vk::ImageMemoryBarrier{
|
||||||
|
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
|
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
|
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
|
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
||||||
|
.image = plainTexture.m_Image,
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::Fence fence;
|
vk::Fence fence;
|
||||||
|
|
@ -268,15 +325,15 @@ 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,
|
copyBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eTransfer, {}, 0,
|
||||||
nullptr, 0, nullptr, 1, &imageReadyToWrite);
|
nullptr, 0, nullptr, Cast<u32>(imageReadyToWrite.size()), imageReadyToWrite.data());
|
||||||
|
|
||||||
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = vertexStaging.GetSize()};
|
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = vertexStaging.GetSize()};
|
||||||
copyBuffer.copyBuffer(vertexStaging.m_Buffer, vbo.m_Buffer, 1, &bufferCopy);
|
copyBuffer.copyBuffer(vertexStaging.m_Buffer, vbo.m_Buffer, 1, &bufferCopy);
|
||||||
|
|
||||||
vk::BufferImageCopy imageCopy = {
|
vk::BufferImageCopy imageCopy = {
|
||||||
.bufferOffset = 0,
|
.bufferOffset = 0,
|
||||||
.bufferRowLength = imageFile.m_Width,
|
.bufferRowLength = crateImageFile.m_Width,
|
||||||
.bufferImageHeight = imageFile.m_Height,
|
.bufferImageHeight = crateImageFile.m_Height,
|
||||||
.imageSubresource =
|
.imageSubresource =
|
||||||
{
|
{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
|
@ -285,13 +342,15 @@ main(int, char **)
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
.imageOffset = {},
|
.imageOffset = {},
|
||||||
.imageExtent = {imageFile.m_Width, imageFile.m_Height, 1},
|
.imageExtent = {crateImageFile.m_Width, crateImageFile.m_Height, 1},
|
||||||
};
|
};
|
||||||
copyBuffer.copyBufferToImage(imageStaging.m_Buffer, crate.m_Image, vk::ImageLayout::eTransferDstOptimal, 1,
|
copyBuffer.copyBufferToImage(imageStaging1.m_Buffer, crateTexture.m_Image, vk::ImageLayout::eTransferDstOptimal,
|
||||||
&imageCopy);
|
1, &imageCopy);
|
||||||
|
copyBuffer.copyBufferToImage(imageStaging2.m_Buffer, plainTexture.m_Image, vk::ImageLayout::eTransferDstOptimal,
|
||||||
|
1, &imageCopy);
|
||||||
|
|
||||||
copyBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {},
|
copyBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {},
|
||||||
0, nullptr, 0, nullptr, 1, &imageReadyToRead);
|
0, nullptr, 0, nullptr, Cast<u32>(imageReadyToRead.size()), imageReadyToRead.data());
|
||||||
|
|
||||||
AbortIfFailed(copyBuffer.end());
|
AbortIfFailed(copyBuffer.end());
|
||||||
|
|
||||||
|
|
@ -310,49 +369,8 @@ main(int, char **)
|
||||||
|
|
||||||
device.m_Device.destroy(fence, nullptr);
|
device.m_Device.destroy(fence, nullptr);
|
||||||
vertexStaging.Destroy(&device);
|
vertexStaging.Destroy(&device);
|
||||||
imageStaging.Destroy(&device);
|
imageStaging1.Destroy(&device);
|
||||||
}
|
imageStaging2.Destroy(&device);
|
||||||
|
|
||||||
vk::ImageView imageView;
|
|
||||||
vk::Sampler sampler;
|
|
||||||
{
|
|
||||||
vk::ImageViewCreateInfo imageViewCreateInfo = {
|
|
||||||
.image = crate.m_Image,
|
|
||||||
.viewType = vk::ImageViewType::e2D,
|
|
||||||
.format = vk::Format::eR8G8B8A8Srgb,
|
|
||||||
.components =
|
|
||||||
vk::ComponentMapping{
|
|
||||||
.r = vk::ComponentSwizzle::eIdentity,
|
|
||||||
.g = vk::ComponentSwizzle::eIdentity,
|
|
||||||
.b = vk::ComponentSwizzle::eIdentity,
|
|
||||||
.a = vk::ComponentSwizzle::eIdentity,
|
|
||||||
},
|
|
||||||
.subresourceRange =
|
|
||||||
{
|
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
AbortIfFailed(device.m_Device.createImageView(&imageViewCreateInfo, nullptr, &imageView));
|
|
||||||
vk::SamplerCreateInfo samplerCreateInfo = {
|
|
||||||
.magFilter = vk::Filter::eLinear,
|
|
||||||
.minFilter = vk::Filter::eLinear,
|
|
||||||
.mipmapMode = vk::SamplerMipmapMode::eLinear,
|
|
||||||
.addressModeU = vk::SamplerAddressMode::eRepeat,
|
|
||||||
.addressModeV = vk::SamplerAddressMode::eRepeat,
|
|
||||||
.addressModeW = vk::SamplerAddressMode::eRepeat,
|
|
||||||
.mipLodBias = 0.2,
|
|
||||||
.anisotropyEnable = true,
|
|
||||||
.maxAnisotropy = 1.0f,
|
|
||||||
.compareEnable = false,
|
|
||||||
.minLod = 0,
|
|
||||||
.maxLod = 4,
|
|
||||||
.unnormalizedCoordinates = false,
|
|
||||||
};
|
|
||||||
AbortIfFailed(device.m_Device.createSampler(&samplerCreateInfo, nullptr, &sampler));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformBuffer ubo;
|
UniformBuffer ubo;
|
||||||
|
|
@ -363,11 +381,6 @@ main(int, char **)
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.range = ubo.GetSize(),
|
.range = ubo.GetSize(),
|
||||||
};
|
};
|
||||||
vk::DescriptorImageInfo descriptorImageInfo = {
|
|
||||||
.sampler = sampler,
|
|
||||||
.imageView = imageView,
|
|
||||||
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
|
||||||
};
|
|
||||||
eastl::array writeDescriptors = {
|
eastl::array writeDescriptors = {
|
||||||
vk::WriteDescriptorSet{
|
vk::WriteDescriptorSet{
|
||||||
.dstSet = descriptorSet,
|
.dstSet = descriptorSet,
|
||||||
|
|
@ -377,17 +390,11 @@ main(int, char **)
|
||||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||||
.pBufferInfo = &descriptorBufferInfo,
|
.pBufferInfo = &descriptorBufferInfo,
|
||||||
},
|
},
|
||||||
vk::WriteDescriptorSet{
|
|
||||||
.dstSet = descriptorSet,
|
|
||||||
.dstBinding = 1,
|
|
||||||
.dstArrayElement = 0,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
|
||||||
.pImageInfo = &descriptorImageInfo,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
device.m_Device.updateDescriptorSets(Cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
|
device.m_Device.updateDescriptorSets(Cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
|
||||||
|
|
||||||
|
resourceManager.Update();
|
||||||
|
|
||||||
// Persistent variables
|
// Persistent variables
|
||||||
vk::Viewport viewport = {
|
vk::Viewport viewport = {
|
||||||
.x = 0,
|
.x = 0,
|
||||||
|
|
@ -487,11 +494,27 @@ main(int, char **)
|
||||||
|
|
||||||
Time::Init();
|
Time::Init();
|
||||||
|
|
||||||
|
Handle *pushData = &crateTextureId;
|
||||||
|
Handle *otherPushData = &plainTextureId;
|
||||||
|
|
||||||
|
bool prevPressed = false;
|
||||||
|
auto isSpaceJustPressed = [&prevPressed, &window] {
|
||||||
|
bool pressed = glfwGetKey(window.m_Window, GLFW_KEY_SPACE) == GLFW_PRESS;
|
||||||
|
bool justPressed = pressed & !prevPressed;
|
||||||
|
prevPressed = pressed;
|
||||||
|
return justPressed;
|
||||||
|
};
|
||||||
|
|
||||||
INFO("Starting loop");
|
INFO("Starting loop");
|
||||||
while (window.Poll())
|
while (window.Poll())
|
||||||
{
|
{
|
||||||
Time::Update();
|
Time::Update();
|
||||||
|
|
||||||
|
if (isSpaceJustPressed())
|
||||||
|
{
|
||||||
|
eastl::swap(pushData, otherPushData);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
@ -546,6 +569,9 @@ main(int, char **)
|
||||||
cmd.setViewport(0, 1, &viewport);
|
cmd.setViewport(0, 1, &viewport);
|
||||||
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.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, 0, sizeof *pushData, pushData);
|
||||||
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1,
|
||||||
|
&resourceManager.m_DescriptorSet, 0, nullptr);
|
||||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 1, 1, &descriptorSet, 0, nullptr);
|
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 1, 1, &descriptorSet, 0, nullptr);
|
||||||
usize offsets = 0;
|
usize offsets = 0;
|
||||||
cmd.bindVertexBuffers(0, 1, &vbo.m_Buffer, &offsets);
|
cmd.bindVertexBuffers(0, 1, &vbo.m_Buffer, &offsets);
|
||||||
|
|
@ -583,12 +609,11 @@ main(int, char **)
|
||||||
{
|
{
|
||||||
depthImage.Destroy(&device);
|
depthImage.Destroy(&device);
|
||||||
}
|
}
|
||||||
device.m_Device.destroy(sampler, nullptr);
|
|
||||||
device.m_Device.destroy(imageView, nullptr);
|
|
||||||
ubo.Destroy(&device);
|
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);
|
crateTexture.Destroy(&device);
|
||||||
|
plainTexture.Destroy(&device);
|
||||||
vbo.Destroy(&device);
|
vbo.Destroy(&device);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -598,27 +623,60 @@ bool
|
||||||
ImageFile::Load(vec4 color)
|
ImageFile::Load(vec4 color)
|
||||||
{
|
{
|
||||||
constexpr usize size = 512llu * 512llu * 4llu;
|
constexpr usize size = 512llu * 512llu * 4llu;
|
||||||
m_Data = new u8[size];
|
u8 *pData = new u8[size];
|
||||||
|
|
||||||
vec4 color255 = 255.999f * color;
|
vec4 color255 = 255.999f * color;
|
||||||
glm::vec<4, u8> color8 = color255;
|
glm::vec<4, u8> color8 = color255;
|
||||||
|
|
||||||
for (usize i = 0; i < size; i += 4)
|
for (usize i = 0; i < size; i += 4)
|
||||||
{
|
{
|
||||||
memcpy(m_Data + i, &color8, sizeof color8);
|
memcpy(pData + i, &color8, sizeof color8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_Data = pData;
|
||||||
|
m_Constant = true;
|
||||||
|
m_Height = 512;
|
||||||
|
m_Width = 512;
|
||||||
|
m_NumChannels = 4;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ImageFile::Load(cstr fileName)
|
||||||
|
{
|
||||||
|
int width, height, nrChannels;
|
||||||
|
m_Data = stbi_load(fileName, &width, &height, &nrChannels, 4);
|
||||||
|
ERROR_IF(!m_Data, "Could not load {}", fileName);
|
||||||
|
|
||||||
|
if (!m_Data)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Width = width;
|
||||||
|
m_Height = height;
|
||||||
|
m_NumChannels = 4;
|
||||||
|
m_Constant = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
usize
|
usize
|
||||||
ImageFile::GetSize() const
|
ImageFile::GetSize() const
|
||||||
{
|
{
|
||||||
return m_Width * m_Height * m_NumChannels;
|
return Cast<usize>(m_Width) * m_Height * m_NumChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageFile::~ImageFile()
|
ImageFile::~ImageFile()
|
||||||
{
|
{
|
||||||
delete[] m_Data;
|
if (m_Constant)
|
||||||
|
{
|
||||||
|
delete[] Cast<u8 *>(m_Data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stbi_image_free(m_Data);
|
||||||
|
}
|
||||||
m_Data = nullptr;
|
m_Data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -44,12 +44,6 @@ CreatePipeline(const Device *device, const Swapchain *swapchain, const RenderRes
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eVertex,
|
.stageFlags = vk::ShaderStageFlagBits::eVertex,
|
||||||
},
|
},
|
||||||
vk::DescriptorSetLayoutBinding{
|
|
||||||
.binding = 1,
|
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
|
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
|
||||||
|
|
@ -61,11 +55,17 @@ CreatePipeline(const Device *device, const Swapchain *swapchain, const RenderRes
|
||||||
descriptorSetLayouts.push_back(descriptorSetLayout);
|
descriptorSetLayouts.push_back(descriptorSetLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::PushConstantRange pushConstantRange = {
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
|
.offset = 0,
|
||||||
|
.size = 16,
|
||||||
|
};
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
||||||
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
|
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
|
||||||
.pSetLayouts = descriptorSetLayouts.data(),
|
.pSetLayouts = descriptorSetLayouts.data(),
|
||||||
.pushConstantRangeCount = 0,
|
.pushConstantRangeCount = 1,
|
||||||
.pPushConstantRanges = nullptr,
|
.pPushConstantRanges = &pushConstantRange,
|
||||||
};
|
};
|
||||||
vk::PipelineLayout pipelineLayout;
|
vk::PipelineLayout pipelineLayout;
|
||||||
AbortIfFailed(device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
AbortIfFailed(device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||||
|
|
|
||||||
|
|
@ -10,45 +10,148 @@
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
RenderResourceManager::RenderResourceManager(const Device *device)
|
#include <EASTL/array.h>
|
||||||
|
|
||||||
|
RenderResourceManager::WriteInfo::WriteInfo(vk::DescriptorBufferInfo info)
|
||||||
|
: uBufferInfo(info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderResourceManager::WriteInfo::WriteInfo(vk::DescriptorImageInfo info)
|
||||||
|
: uImageInfo(info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderResourceManager::WriteInfo::WriteInfo(vk::BufferView info)
|
||||||
|
: uBufferView(info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferHandle
|
||||||
|
RenderResourceManager::Commit(const UniformStorageBuffer *storageBuffer)
|
||||||
|
{
|
||||||
|
const u32 handle = m_BufferFreeList.Alloc();
|
||||||
|
|
||||||
|
m_WriteInfos.emplace_back(vk::DescriptorBufferInfo{
|
||||||
|
.buffer = storageBuffer->m_Buffer,
|
||||||
|
.offset = 0,
|
||||||
|
.range = storageBuffer->GetSize(),
|
||||||
|
});
|
||||||
|
|
||||||
|
m_Writes.push_back({
|
||||||
|
.dstSet = m_DescriptorSet,
|
||||||
|
.dstBinding = BUFFER_BINDING_INDEX,
|
||||||
|
.dstArrayElement = handle,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||||
|
.pBufferInfo = &m_WriteInfos.back().uBufferInfo,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {handle};
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureHandle
|
||||||
|
RenderResourceManager::Commit(const Texture *texture)
|
||||||
|
{
|
||||||
|
const u32 handle = m_TextureFreeList.Alloc();
|
||||||
|
|
||||||
|
m_WriteInfos.emplace_back(vk::DescriptorImageInfo{
|
||||||
|
.sampler = nullptr,
|
||||||
|
.imageView = texture->m_View,
|
||||||
|
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
|
});
|
||||||
|
|
||||||
|
m_Writes.push_back({
|
||||||
|
.dstSet = m_DescriptorSet,
|
||||||
|
.dstBinding = TEXTURE_BINDING_INDEX,
|
||||||
|
.dstArrayElement = handle,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.pImageInfo = &m_WriteInfos.back().uImageInfo,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {handle};
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RenderResourceManager::Update()
|
||||||
|
{
|
||||||
|
usize count = Cast<usize>(m_Writes.size());
|
||||||
|
vk::WriteDescriptorSet *pData = m_Writes.data();
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
m_Device->m_Device.updateDescriptorSets(count, pData, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Writes.clear();
|
||||||
|
m_WriteInfos.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderResourceManager::RenderResourceManager(const Device *device, u16 maxSize)
|
||||||
: m_Device(device)
|
: m_Device(device)
|
||||||
{
|
{
|
||||||
vk::PhysicalDeviceProperties properties;
|
vk::PhysicalDeviceProperties properties;
|
||||||
m_Device->m_PhysicalDevice.getProperties(&properties);
|
m_Device->m_PhysicalDevice.getProperties(&properties);
|
||||||
|
|
||||||
auto maxBufferCount = properties.limits.maxDescriptorSetStorageBuffers - 1024;
|
u32 buffersCount = eastl::min(properties.limits.maxPerStageDescriptorStorageBuffers - 1024, Cast<u32>(maxSize));
|
||||||
auto maxTextureCount = properties.limits.maxDescriptorSetSampledImages - 1024;
|
u32 texturesCount = eastl::min(properties.limits.maxPerStageDescriptorSampledImages - 1024, Cast<u32>(maxSize));
|
||||||
|
|
||||||
INFO("Max Buffer Count: {}", maxBufferCount);
|
vk::SamplerCreateInfo samplerCreateInfo = {
|
||||||
INFO("Max Texture Count: {}", maxTextureCount);
|
.magFilter = vk::Filter::eLinear,
|
||||||
|
.minFilter = vk::Filter::eLinear,
|
||||||
|
.mipmapMode = vk::SamplerMipmapMode::eLinear,
|
||||||
|
.addressModeU = vk::SamplerAddressMode::eClampToBorder,
|
||||||
|
.addressModeV = vk::SamplerAddressMode::eClampToBorder,
|
||||||
|
.addressModeW = vk::SamplerAddressMode::eClampToBorder,
|
||||||
|
.mipLodBias = 0.0f,
|
||||||
|
.anisotropyEnable = true,
|
||||||
|
.maxAnisotropy = properties.limits.maxSamplerAnisotropy,
|
||||||
|
.compareEnable = false,
|
||||||
|
.minLod = 0,
|
||||||
|
.maxLod = vk::LodClampNone,
|
||||||
|
.borderColor = vk::BorderColor::eFloatOpaqueBlack,
|
||||||
|
.unnormalizedCoordinates = false,
|
||||||
|
};
|
||||||
|
AbortIfFailed(device->m_Device.createSampler(&samplerCreateInfo, nullptr, &m_Sampler));
|
||||||
|
|
||||||
m_Buffers.resize(maxBufferCount);
|
INFO("Max Buffer Count: {}", buffersCount);
|
||||||
m_Textures.resize(maxTextureCount);
|
INFO("Max Texture Count: {}", texturesCount);
|
||||||
|
|
||||||
|
m_BufferFreeList.Init(buffersCount);
|
||||||
|
m_TextureFreeList.Init(texturesCount);
|
||||||
|
|
||||||
eastl::array poolSizes = {
|
eastl::array poolSizes = {
|
||||||
vk::DescriptorPoolSize{.type = vk::DescriptorType::eStorageBuffer, .descriptorCount = maxBufferCount},
|
vk::DescriptorPoolSize{
|
||||||
vk::DescriptorPoolSize{.type = vk::DescriptorType::eSampledImage, .descriptorCount = maxTextureCount},
|
.type = vk::DescriptorType::eStorageBuffer,
|
||||||
|
.descriptorCount = buffersCount,
|
||||||
|
},
|
||||||
|
vk::DescriptorPoolSize{
|
||||||
|
.type = vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
.descriptorCount = texturesCount,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorPoolCreateInfo poolCreateInfo = {
|
const vk::DescriptorPoolCreateInfo poolCreateInfo = {
|
||||||
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
|
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
|
||||||
.maxSets = 4,
|
.maxSets = 1,
|
||||||
.poolSizeCount = Cast<u32>(poolSizes.size()),
|
.poolSizeCount = Cast<u32>(poolSizes.size()),
|
||||||
.pPoolSizes = poolSizes.data(),
|
.pPoolSizes = poolSizes.data(),
|
||||||
};
|
};
|
||||||
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
||||||
|
|
||||||
|
eastl::vector immutableSamplers(texturesCount, m_Sampler);
|
||||||
eastl::array descriptorLayoutBindings = {
|
eastl::array descriptorLayoutBindings = {
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = 0,
|
.binding = BUFFER_BINDING_INDEX,
|
||||||
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||||
.descriptorCount = Cast<u32>(m_Buffers.size()),
|
.descriptorCount = Cast<u32>(buffersCount),
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
},
|
},
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = 1,
|
.binding = TEXTURE_BINDING_INDEX,
|
||||||
.descriptorType = vk::DescriptorType::eSampledImage,
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
.descriptorCount = Cast<u32>(m_Textures.size()),
|
.descriptorCount = Cast<u32>(texturesCount),
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
|
.pImmutableSamplers = immutableSamplers.data(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
|
|
@ -71,17 +174,7 @@ RenderResourceManager::RenderResourceManager(const Device *device)
|
||||||
|
|
||||||
RenderResourceManager::~RenderResourceManager()
|
RenderResourceManager::~RenderResourceManager()
|
||||||
{
|
{
|
||||||
for (auto &buffer : m_Buffers)
|
m_Device->m_Device.destroy(m_Sampler, nullptr);
|
||||||
{
|
|
||||||
buffer.Destroy(m_Device);
|
|
||||||
}
|
|
||||||
for (auto &image : m_Textures)
|
|
||||||
{
|
|
||||||
image.Destroy(m_Device);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Device->m_Device.destroy(m_TextureUpdate, nullptr);
|
|
||||||
m_Device->m_Device.destroy(m_BufferUpdate, nullptr);
|
|
||||||
m_Device->m_Device.destroy(m_DescriptorPool, nullptr);
|
m_Device->m_Device.destroy(m_DescriptorPool, nullptr);
|
||||||
m_Device->m_Device.destroy(m_SetLayout, nullptr);
|
m_Device->m_Device.destroy(m_SetLayout, nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -7,16 +7,18 @@
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/deque.h>
|
||||||
#include <EASTL/vector.h>
|
#include <EASTL/stack.h>
|
||||||
|
|
||||||
struct Device;
|
struct Device;
|
||||||
struct Texture;
|
struct Texture;
|
||||||
struct UniformBuffer;
|
struct UniformStorageBuffer;
|
||||||
|
|
||||||
|
struct RenderResourceManager;
|
||||||
|
|
||||||
struct Handle
|
struct Handle
|
||||||
{
|
{
|
||||||
u16 m_Index;
|
u32 m_Index;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BufferHandle : Handle
|
struct BufferHandle : Handle
|
||||||
|
|
@ -27,29 +29,81 @@ struct TextureHandle : Handle
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FreeList
|
||||||
|
{
|
||||||
|
eastl::stack<u32, eastl::deque<u32>> m_List;
|
||||||
|
u32 m_MaxVisited = 0;
|
||||||
|
u32 m_MaxCapacity = 16;
|
||||||
|
|
||||||
|
void
|
||||||
|
Init(u32 maxCapacity)
|
||||||
|
{
|
||||||
|
m_MaxCapacity = maxCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] u32
|
||||||
|
Alloc()
|
||||||
|
{
|
||||||
|
if (!m_List.empty())
|
||||||
|
{
|
||||||
|
const u32 value = m_List.top();
|
||||||
|
m_List.pop();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
if (m_MaxVisited < m_MaxCapacity)
|
||||||
|
{
|
||||||
|
return m_MaxVisited++;
|
||||||
|
}
|
||||||
|
ERROR("Out of Handles.") THEN_ABORT(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Free(u32 index)
|
||||||
|
{
|
||||||
|
WARN_IF(index >= m_MaxCapacity, "Trying to free an out-of-bounds index.");
|
||||||
|
|
||||||
|
if (index < m_MaxCapacity)
|
||||||
|
m_List.push(index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct RenderResourceManager
|
struct RenderResourceManager
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
union WriteInfo {
|
||||||
|
vk::DescriptorBufferInfo uBufferInfo;
|
||||||
|
vk::DescriptorImageInfo uImageInfo;
|
||||||
|
vk::BufferView uBufferView;
|
||||||
|
|
||||||
|
explicit WriteInfo(vk::DescriptorBufferInfo info);
|
||||||
|
explicit WriteInfo(vk::DescriptorImageInfo info);
|
||||||
|
explicit WriteInfo(vk::BufferView info);
|
||||||
|
};
|
||||||
|
|
||||||
|
eastl::deque<WriteInfo> m_WriteInfos;
|
||||||
|
eastl::vector<vk::WriteDescriptorSet> m_Writes;
|
||||||
|
|
||||||
|
vk::Sampler m_Sampler;
|
||||||
|
|
||||||
|
FreeList m_BufferFreeList;
|
||||||
|
FreeList m_TextureFreeList;
|
||||||
|
|
||||||
|
public:
|
||||||
const Device *m_Device;
|
const Device *m_Device;
|
||||||
|
|
||||||
|
constexpr static u32 BUFFER_BINDING_INDEX = 0;
|
||||||
|
constexpr static u32 TEXTURE_BINDING_INDEX = 1;
|
||||||
|
|
||||||
vk::DescriptorPool m_DescriptorPool;
|
vk::DescriptorPool m_DescriptorPool;
|
||||||
vk::DescriptorSetLayout m_SetLayout;
|
vk::DescriptorSetLayout m_SetLayout;
|
||||||
vk::DescriptorSet m_DescriptorSet;
|
vk::DescriptorSet m_DescriptorSet;
|
||||||
|
|
||||||
vk::DescriptorUpdateTemplate m_BufferUpdate;
|
BufferHandle Commit(const UniformStorageBuffer *storageBuffer);
|
||||||
vk::DescriptorUpdateTemplate m_TextureUpdate;
|
TextureHandle Commit(const Texture *texture);
|
||||||
|
|
||||||
eastl::vector<UniformBuffer> m_Buffers;
|
void Update();
|
||||||
eastl::vector<Texture> m_Textures;
|
|
||||||
// TODO: eastl::vector<StorageTexture> m_Textures;
|
|
||||||
|
|
||||||
// UniformBuffer *Allocate();
|
|
||||||
// UniformBuffer *Fetch(UniformHandle handle);
|
|
||||||
// void Commit(UniformHandle handle);
|
|
||||||
// Texture *Allocate();
|
|
||||||
// Texture *Fetch(TextureHandle handle);
|
|
||||||
// void Commit(TextureHandle handle);
|
|
||||||
|
|
||||||
// Ctor/Dtor
|
// Ctor/Dtor
|
||||||
explicit RenderResourceManager(const Device *device);
|
explicit RenderResourceManager(const Device *device, u16 maxSize);
|
||||||
~RenderResourceManager();
|
~RenderResourceManager();
|
||||||
};
|
};
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
#version 450
|
#version 450
|
||||||
#pragma shader_stage(fragment)
|
#pragma shader_stage(fragment)
|
||||||
|
#extension GL_EXT_nonuniform_qualifier : enable
|
||||||
|
|
||||||
layout (location = 0) in vec2 inUV;
|
layout (location = 0) in vec2 inUV;
|
||||||
layout (location = 0) out vec4 outColor;
|
layout (location = 0) out vec4 outColor;
|
||||||
|
|
||||||
layout(set = 1, binding = 1) uniform sampler2D tex;
|
layout(set = 0, binding = 1) uniform sampler2D textures[];
|
||||||
|
|
||||||
|
layout(push_constant) uniform Block {
|
||||||
|
uint handle;
|
||||||
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
outColor = vec4(texture(tex, inUV).rgb, 1.0f);
|
outColor = vec4(texture(textures[handle], inUV).rgb, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#version 450
|
#version 450
|
||||||
#pragma shader_stage(vertex)
|
#pragma shader_stage(vertex)
|
||||||
|
#extension GL_EXT_nonuniform_qualifier : enable
|
||||||
|
|
||||||
layout(location = 0) in vec4 position;
|
layout(location = 0) in vec4 position;
|
||||||
layout(location = 1) in vec2 uv0;
|
layout(location = 1) in vec2 uv0;
|
||||||
|
|
@ -7,7 +8,7 @@ layout(location = 1) in vec2 uv0;
|
||||||
layout(location = 0) out vec2 outUV;
|
layout(location = 0) out vec2 outUV;
|
||||||
|
|
||||||
//layout(std140, set=0, binding=0) readonly buffer buffers;
|
//layout(std140, set=0, binding=0) readonly buffer buffers;
|
||||||
layout(set = 0, binding = 1) uniform texture2D textures[];
|
//layout(set = 0, binding = 1) uniform texture2D textures[];
|
||||||
|
|
||||||
layout(set = 1, binding = 0) uniform Camera {
|
layout(set = 1, binding = 0) uniform Camera {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue