Compare commits
No commits in common. "8ea9cf5bef72d4c1a0ffb40ec30d24df03f8b4a2" and "b9dcf5e4ec3a190e42bda95740fdd030df68e377" have entirely different histories.
8ea9cf5bef
...
b9dcf5e4ec
|
|
@ -11,11 +11,11 @@
|
|||
void
|
||||
Buffer::Destroy(const Device *device)
|
||||
{
|
||||
if (!IsValid() || !IsOwned())
|
||||
if (!IsValid())
|
||||
return;
|
||||
|
||||
vmaDestroyBuffer(device->m_Allocator, m_Buffer, m_Allocation);
|
||||
m_Size_ = 0;
|
||||
m_Size &= ~VALID_BUFFER_BIT;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -47,7 +47,7 @@ Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUs
|
|||
bool hostAccessible = Cast<bool>(memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible);
|
||||
|
||||
m_Buffer = buffer;
|
||||
m_Size_ = size | VALID_BUFFER_BIT | OWNED_BIT | (hostAccessible ? HOST_ACCESSIBLE_BIT : 0);
|
||||
m_Size = size | VALID_BUFFER_BIT | (hostAccessible ? HOST_ACCESSIBLE_BIT : 0);
|
||||
m_Allocation = allocation;
|
||||
m_Mapped = Cast<u8 *>(allocationInfo.pMappedData);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,27 +19,23 @@ struct Buffer
|
|||
[[nodiscard]] bool IsHostVisible() const;
|
||||
[[nodiscard]] bool IsValid() const;
|
||||
[[nodiscard]] bool IsMapped() const;
|
||||
[[nodiscard]] bool IsOwned() const;
|
||||
|
||||
void Destroy(const Device *device);
|
||||
void Write(const Device *device, usize offset, usize size, const void *data);
|
||||
|
||||
protected:
|
||||
void Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUsage,
|
||||
VmaAllocationCreateFlags allocationFlags, VmaMemoryUsage memoryUsage, cstr name);
|
||||
|
||||
// Buffer.size is used for bookkeeping
|
||||
// If the buffer is Invalid, the remaining data in Buffer is used intrusively by `GpuResourceManager`.
|
||||
usize m_Size_ = 0;
|
||||
// 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;
|
||||
|
||||
constexpr static usize VALID_BUFFER_BIT = Cast<usize>(1llu << 63);
|
||||
constexpr static usize HOST_ACCESSIBLE_BIT = 1llu << 62;
|
||||
constexpr static usize OWNED_BIT = 1llu << 61;
|
||||
constexpr static usize SIZE_MASK = ~(VALID_BUFFER_BIT | HOST_ACCESSIBLE_BIT | OWNED_BIT);
|
||||
constexpr static usize SIZE_MASK = ~(VALID_BUFFER_BIT | HOST_ACCESSIBLE_BIT);
|
||||
};
|
||||
|
||||
// Ensure that m_Size doesn't get used intrusively since it manages the state.
|
||||
static_assert(offsetof(Buffer, m_Size_) > sizeof(usize));
|
||||
|
||||
struct UniformBuffer : Buffer
|
||||
{
|
||||
void Init(const Device *device, usize size, cstr name = nullptr);
|
||||
|
|
@ -70,19 +66,19 @@ struct StagingBuffer : Buffer
|
|||
inline usize
|
||||
Buffer::GetSize() const
|
||||
{
|
||||
return m_Size_ & SIZE_MASK;
|
||||
return m_Size & SIZE_MASK;
|
||||
}
|
||||
|
||||
inline bool
|
||||
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;
|
||||
return m_Size & VALID_BUFFER_BIT;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
|
@ -90,9 +86,3 @@ Buffer::IsMapped() const
|
|||
{
|
||||
return m_Mapped;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Buffer::IsOwned() const
|
||||
{
|
||||
return m_Size_ & OWNED_BIT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||
#define GLM_FORCE_QUATERNIONS_XYZW
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ using glm::ivec4;
|
|||
using glm::vec2;
|
||||
using glm::vec3;
|
||||
using glm::vec4;
|
||||
using glm::quat;
|
||||
|
||||
using glm::mat2;
|
||||
using glm::mat3;
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@
|
|||
void
|
||||
Image::Destroy(const Device *device)
|
||||
{
|
||||
if (!IsValid() || !IsOwned())
|
||||
if (!IsValid())
|
||||
return;
|
||||
|
||||
device->m_Device.destroy(m_View, nullptr);
|
||||
vmaDestroyImage(device->m_Allocator, m_Image, m_Allocation);
|
||||
m_MipLevels_ = 0;
|
||||
m_Image = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -23,7 +23,6 @@ Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageF
|
|||
const cstr name)
|
||||
{
|
||||
const u32 mipLevels = isMipmapped ? 1 + Cast<u32>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
|
||||
assert(mipLevels <= MIP_MASK);
|
||||
|
||||
auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
|
||||
if (isMipmapped)
|
||||
|
|
@ -76,7 +75,7 @@ Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageF
|
|||
m_View = view;
|
||||
m_Allocation = allocation;
|
||||
m_Extent = {extent.width, extent.height, 1};
|
||||
m_MipLevels_ = mipLevels | OWNED_BIT | VALID_BIT;
|
||||
m_MipLevels = Cast<u8>(mipLevels);
|
||||
|
||||
device->SetName(m_Image, name);
|
||||
}
|
||||
|
|
@ -130,7 +129,6 @@ DepthImage::Init(const Device *device, vk::Extent2D extent, cstr name)
|
|||
m_View = view;
|
||||
m_Allocation = allocation;
|
||||
m_Extent = {extent.width, extent.height, 1};
|
||||
m_MipLevels_ = 1 | OWNED_BIT | VALID_BIT;
|
||||
|
||||
device->SetName(m_Image, name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,19 +15,11 @@ struct Image
|
|||
vk::ImageView m_View = nullptr;
|
||||
VmaAllocation m_Allocation = nullptr;
|
||||
vk::Extent3D m_Extent;
|
||||
// Image.m_MipLevels_ is used for bookkeeping
|
||||
// If the image is Invalid, the remaining data in Image is used intrusively by `GpuResourceManager`.
|
||||
u32 m_MipLevels_;
|
||||
u8 m_MipLevels = 1;
|
||||
|
||||
[[nodiscard]] bool IsValid() const;
|
||||
[[nodiscard]] bool IsOwned() const;
|
||||
[[nodiscard]] u32 GetMipLevels() const;
|
||||
|
||||
void Destroy(const Device *device);
|
||||
|
||||
constexpr static u32 VALID_BIT = 1u << 31;
|
||||
constexpr static u32 OWNED_BIT = 1u << 30;
|
||||
constexpr static u32 MIP_MASK = ~(VALID_BIT | OWNED_BIT);
|
||||
};
|
||||
|
||||
struct Texture : Image
|
||||
|
|
@ -43,17 +35,5 @@ struct DepthImage : Image
|
|||
inline bool
|
||||
Image::IsValid() const
|
||||
{
|
||||
return m_MipLevels_ & VALID_BIT;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Image::IsOwned() const
|
||||
{
|
||||
return m_MipLevels_ & OWNED_BIT;
|
||||
}
|
||||
|
||||
inline u32
|
||||
Image::GetMipLevels() const
|
||||
{
|
||||
return m_MipLevels_ & MIP_MASK;
|
||||
return m_Image;
|
||||
}
|
||||
BIN
samples/03_model_render/model/BoxVertexColors.glb (Stored with Git LFS)
BIN
samples/03_model_render/model/BoxVertexColors.glb (Stored with Git LFS)
Binary file not shown.
BIN
samples/03_model_render/model/OrientationTest.glb (Stored with Git LFS)
BIN
samples/03_model_render/model/OrientationTest.glb (Stored with Git LFS)
Binary file not shown.
|
|
@ -18,7 +18,6 @@
|
|||
#include "image.h"
|
||||
#include "render_resource_manager.h"
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <EASTL/array.h>
|
||||
|
||||
vec4
|
||||
|
|
@ -46,16 +45,14 @@ VectorToVec3(const std::vector<double> &vec)
|
|||
}
|
||||
|
||||
TextureHandle
|
||||
ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBuffer,
|
||||
ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, Texture *texture, StagingBuffer *stagingBuffer,
|
||||
tinygltf::Image *image) const
|
||||
{
|
||||
assert(image->component == 4);
|
||||
|
||||
Texture texture;
|
||||
|
||||
usize byteSize = image->image.size();
|
||||
texture.Init(m_ResourceManager->m_Device, {.width = Cast<u32>(image->width), .height = Cast<u32>(image->height)},
|
||||
vk::Format::eR8G8B8A8Srgb, true, image->name.data());
|
||||
texture->Init(m_ResourceManager->m_Device, {.width = Cast<u32>(image->width), .height = Cast<u32>(image->height)},
|
||||
vk::Format::eR8G8B8A8Srgb, true, image->name.data());
|
||||
stagingBuffer->Init(m_ResourceManager->m_Device, byteSize);
|
||||
stagingBuffer->Write(m_ResourceManager->m_Device, 0, byteSize, image->image.data());
|
||||
|
||||
|
|
@ -66,15 +63,15 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu
|
|||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||
.image = texture.m_Image,
|
||||
.image = texture->m_Image,
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = texture.GetMipLevels(),
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = texture->m_MipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
vk::ImageMemoryBarrier nextMipBarrier = {
|
||||
|
|
@ -84,15 +81,15 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu
|
|||
.newLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||
.image = texture.m_Image,
|
||||
.image = texture->m_Image,
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
vk::ImageMemoryBarrier imageReadyBarrier = {
|
||||
|
|
@ -102,15 +99,15 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu
|
|||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
.srcQueueFamilyIndex = m_TransferQueueIndex,
|
||||
.dstQueueFamilyIndex = m_GraphicsQueueIndex,
|
||||
.image = texture.m_Image,
|
||||
.image = texture->m_Image,
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = texture.GetMipLevels(),
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = texture->m_MipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
vk::BufferImageCopy imageCopy = {
|
||||
|
|
@ -118,31 +115,29 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu
|
|||
.bufferRowLength = Cast<u32>(image->width),
|
||||
.bufferImageHeight = Cast<u32>(image->height),
|
||||
.imageSubresource =
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.imageOffset = {},
|
||||
.imageExtent = texture.m_Extent,
|
||||
.imageExtent = texture->m_Extent,
|
||||
};
|
||||
|
||||
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0,
|
||||
nullptr, 0, nullptr, 1, &imageStartBarrier);
|
||||
commandBuffer.copyBufferToImage(stagingBuffer->m_Buffer, texture.m_Image, vk::ImageLayout::eTransferDstOptimal, 1,
|
||||
commandBuffer.copyBufferToImage(stagingBuffer->m_Buffer, texture->m_Image, vk::ImageLayout::eTransferDstOptimal, 1,
|
||||
&imageCopy);
|
||||
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, 0,
|
||||
nullptr, 0, nullptr, 1, &nextMipBarrier);
|
||||
|
||||
auto calcNextMip = [](i32 prev) {
|
||||
return eastl::max(prev / 2, 1);
|
||||
};
|
||||
auto calcNextMip = [](i32 prev) { return eastl::max(prev / 2, 1); };
|
||||
|
||||
i32 prevMipWidth = Cast<i32>(texture.m_Extent.width);
|
||||
i32 prevMipHeight = Cast<i32>(texture.m_Extent.height);
|
||||
i32 prevMipWidth = Cast<i32>(texture->m_Extent.width);
|
||||
i32 prevMipHeight = Cast<i32>(texture->m_Extent.height);
|
||||
|
||||
u32 maxPrevMip = texture.GetMipLevels() - 1;
|
||||
u32 maxPrevMip = texture->m_MipLevels - 1;
|
||||
for (u32 prevMipLevel = 0; prevMipLevel < maxPrevMip; ++prevMipLevel)
|
||||
{
|
||||
i32 currentMipWidth = calcNextMip(prevMipWidth);
|
||||
|
|
@ -151,31 +146,33 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu
|
|||
|
||||
vk::ImageBlit blitRegion = {
|
||||
.srcSubresource =
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.mipLevel = prevMipLevel,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.srcOffsets = std::array{
|
||||
vk::Offset3D{0, 0, 0},
|
||||
vk::Offset3D{prevMipWidth, prevMipHeight, 1},
|
||||
},
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.mipLevel = prevMipLevel,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.srcOffsets =
|
||||
std::array{
|
||||
vk::Offset3D{0, 0, 0},
|
||||
vk::Offset3D{prevMipWidth, prevMipHeight, 1},
|
||||
},
|
||||
.dstSubresource =
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.mipLevel = currentMipLevel,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.dstOffsets = std::array{
|
||||
vk::Offset3D{0, 0, 0},
|
||||
vk::Offset3D{currentMipWidth, currentMipHeight, 1},
|
||||
},
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.mipLevel = currentMipLevel,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.dstOffsets =
|
||||
std::array{
|
||||
vk::Offset3D{0, 0, 0},
|
||||
vk::Offset3D{currentMipWidth, currentMipHeight, 1},
|
||||
},
|
||||
};
|
||||
|
||||
nextMipBarrier.subresourceRange.baseMipLevel = currentMipLevel;
|
||||
commandBuffer.blitImage(texture.m_Image, vk::ImageLayout::eTransferSrcOptimal, texture.m_Image,
|
||||
commandBuffer.blitImage(texture->m_Image, vk::ImageLayout::eTransferSrcOptimal, texture->m_Image,
|
||||
vk::ImageLayout::eTransferDstOptimal, 1, &blitRegion, vk::Filter::eLinear);
|
||||
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, 0,
|
||||
nullptr, 0, nullptr, 1, &nextMipBarrier);
|
||||
|
|
@ -187,7 +184,7 @@ ModelLoader::LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBu
|
|||
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {},
|
||||
0, nullptr, 0, nullptr, 1, &imageReadyBarrier);
|
||||
|
||||
return m_ResourceManager->Commit(&texture);
|
||||
return m_ResourceManager->Commit(texture);
|
||||
}
|
||||
|
||||
Model
|
||||
|
|
@ -228,6 +225,7 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
}
|
||||
|
||||
eastl::vector<StagingBuffer> stagingBuffers;
|
||||
eastl::vector<Texture> textures;
|
||||
eastl::vector<TextureHandle> textureHandles;
|
||||
|
||||
if (!model.images.empty())
|
||||
|
|
@ -235,13 +233,15 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
u32 numImages = Cast<u32>(model.images.size());
|
||||
|
||||
stagingBuffers.resize(numImages);
|
||||
textures.resize(numImages);
|
||||
textureHandles.resize(numImages);
|
||||
|
||||
auto stagingPtr = stagingBuffers.data();
|
||||
auto texturePtr = textures.data();
|
||||
auto imagePtr = model.images.data();
|
||||
for (TextureHandle &handle : textureHandles)
|
||||
{
|
||||
handle = LoadImage(m_CommandBuffer, stagingPtr++, imagePtr++);
|
||||
handle = LoadImage(m_CommandBuffer, texturePtr++, stagingPtr++, imagePtr++);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -293,33 +293,24 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
eastl::vector<vec4> vertexPositions;
|
||||
eastl::vector<vec4> normalVectors;
|
||||
eastl::vector<vec2> texCoord0;
|
||||
eastl::vector<vec4> color0;
|
||||
eastl::vector<u32> indices;
|
||||
eastl::vector<MeshPrimitive> meshPrimitives;
|
||||
meshPrimitives.reserve(model.meshes.size());
|
||||
|
||||
// Offset, Count
|
||||
eastl::vector<eastl::pair<usize, usize>> meshPrimRanges;
|
||||
meshPrimRanges.reserve(model.meshes.size());
|
||||
|
||||
u32 vertexOffset = 0;
|
||||
u32 normalOffset = 0;
|
||||
u32 texCoord0Offset = 0;
|
||||
u32 color0Offset = 0;
|
||||
i32 normalOffset = 0;
|
||||
i32 texCoord0Offset = 0;
|
||||
u32 indexOffset = 0;
|
||||
|
||||
for (auto &mesh : model.meshes)
|
||||
{
|
||||
meshPrimRanges.emplace_back(meshPrimitives.size(), mesh.primitives.size());
|
||||
for (auto &prim : mesh.primitives)
|
||||
{
|
||||
u32 vertexCount = 0;
|
||||
u32 indexCount = 0;
|
||||
u32 normalCount = 0;
|
||||
u32 texCoord0Count = 0;
|
||||
u32 color0Count = 0;
|
||||
i32 normalCount = 0;
|
||||
i32 texCoord0Count = 0;
|
||||
|
||||
#pragma region Position
|
||||
assert(prim.attributes.contains(APosition));
|
||||
assert(prim.mode == TINYGLTF_MODE_TRIANGLES);
|
||||
{
|
||||
|
|
@ -356,8 +347,7 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
}
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Normal
|
||||
|
||||
// Normal Coords
|
||||
if (prim.attributes.contains(ANormal))
|
||||
{
|
||||
|
|
@ -394,8 +384,7 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
}
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region UV0
|
||||
|
||||
// UV0
|
||||
if (prim.attributes.contains(ATexCoord0))
|
||||
{
|
||||
|
|
@ -411,44 +400,13 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
texCoord0.reserve(vertexPositions.size());
|
||||
|
||||
assert(uvAccessor->type == TINYGLTF_TYPE_VEC2 &&
|
||||
uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT);
|
||||
uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT);
|
||||
{
|
||||
vec2 *data = Recast<vec2 *>(uvBuffer->data.data() + byteOffset);
|
||||
texCoord0.insert(texCoord0.end(), data, data + vertexCount);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Color
|
||||
if (prim.attributes.contains(AColor0))
|
||||
{
|
||||
tinygltf::Accessor *colorAccessor = &model.accessors[prim.attributes[AColor0]];
|
||||
|
||||
assert(colorAccessor->count <= MaxValue<u32>);
|
||||
|
||||
tinygltf::BufferView *colorBufferView = &model.bufferViews[colorAccessor->bufferView];
|
||||
tinygltf::Buffer *colorBuffer = &model.buffers[colorBufferView->buffer];
|
||||
usize byteOffset = (colorAccessor->byteOffset + colorBufferView->byteOffset);
|
||||
|
||||
color0Count = Cast<i32>(colorAccessor->count);
|
||||
color0.reserve(vertexPositions.size());
|
||||
assert(color0Count == vertexCount);
|
||||
|
||||
if (colorAccessor->type == TINYGLTF_TYPE_VEC4)
|
||||
{
|
||||
vec4 *data = Recast<vec4 *>(colorBuffer->data.data() + byteOffset);
|
||||
color0.insert(color0.end(), data, data + vertexCount);
|
||||
}
|
||||
else if (colorAccessor->type == TINYGLTF_TYPE_VEC3)
|
||||
{
|
||||
vec3 *data = Recast<vec3 *>(colorBuffer->data.data() + byteOffset);
|
||||
for (u32 i = 0; i < color0Count; ++i)
|
||||
{
|
||||
color0.push_back(vec4(data[i], 1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Indices
|
||||
// Indices
|
||||
if (prim.indices >= 0)
|
||||
{
|
||||
|
|
@ -488,93 +446,26 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
indices.push_back(i);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
meshPrimitives.push_back({
|
||||
.m_VertexOffset = vertexOffset,
|
||||
.m_NormalOffset = normalCount > 0 ? Cast<i32>(normalOffset) : -1,
|
||||
.m_TexCoord0Offset = texCoord0Count > 0 ? Cast<i32>(texCoord0Offset) : -1,
|
||||
// TODO: Color offset
|
||||
.m_NormalOffset = normalCount > 0 ? normalOffset : -1,
|
||||
.m_TexCoord0Offset = texCoord0Count > 0 ? texCoord0Offset : -1,
|
||||
.m_FirstIndex = indexOffset,
|
||||
.m_IndexCount = indexCount,
|
||||
.m_MaterialIdx = prim.material,
|
||||
.m_TransformIdx = -1,
|
||||
});
|
||||
|
||||
vertexOffset += vertexCount;
|
||||
indexOffset += indexCount;
|
||||
texCoord0Offset += texCoord0Count;
|
||||
normalOffset += normalCount;
|
||||
color0Offset += color0Count;
|
||||
|
||||
assert(normalVectors.empty() || normalVectors.size() == vertexPositions.size());
|
||||
assert(texCoord0.empty() || texCoord0.size() == vertexPositions.size());
|
||||
}
|
||||
}
|
||||
|
||||
Nodes nodes;
|
||||
{
|
||||
if (model.defaultScene >= 0)
|
||||
{
|
||||
eastl::function<void(i32,i32)> processNode = [&processNode, &model, &nodes, &meshPrimRanges, &meshPrimitives](i32 idx, i32 parent) -> void {
|
||||
INFO("parent {} -> idx {}", parent, idx);
|
||||
const auto *node = &model.nodes[idx];
|
||||
|
||||
vec3 nodeTranslation = vec3{0.0f};
|
||||
quat nodeRotation = quat{1.0f, 0.0f, 0.0f, 0.0f};
|
||||
vec3 nodeScale = vec3{1.0f};
|
||||
mat4 nodeMatrix = mat4{1.0f};
|
||||
if (node->translation.size() == 3)
|
||||
{
|
||||
nodeTranslation = glm::make_vec3(node->translation.data());
|
||||
}
|
||||
if (node->rotation.size() == 4)
|
||||
{
|
||||
nodeRotation = glm::make_quat(node->rotation.data());
|
||||
}
|
||||
if (node->scale.size() == 3)
|
||||
{
|
||||
nodeScale = glm::make_vec3(node->scale.data());
|
||||
}
|
||||
if (node->matrix.size() == 16)
|
||||
{
|
||||
nodeMatrix = glm::make_mat4(node->matrix.data());
|
||||
}
|
||||
const mat4 transform =
|
||||
translate(mat4(1.0f), nodeTranslation) * mat4_cast(nodeRotation) * scale(mat4(1.0f), nodeScale) * nodeMatrix;
|
||||
|
||||
const u32 nodeArrayIndex = nodes.Add(transform, parent);
|
||||
if (node->mesh >= 0)
|
||||
{
|
||||
auto [start, count] = meshPrimRanges[node->mesh];
|
||||
const auto end = start + count;
|
||||
for (usize i = start; i != end; ++i)
|
||||
{
|
||||
meshPrimitives[i].m_TransformIdx = nodeArrayIndex;
|
||||
}
|
||||
}
|
||||
|
||||
for (const i32 child : node->children)
|
||||
{
|
||||
processNode(child, idx);
|
||||
}
|
||||
};
|
||||
auto *scene = &model.scenes[model.defaultScene];
|
||||
for (i32 rootNodeIdx : scene->nodes)
|
||||
{
|
||||
processNode(rootNodeIdx, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodes.Update();
|
||||
|
||||
StorageBuffer nodeBuffer;
|
||||
nodeBuffer.Init(pDevice, nodes.GetGlobalTransformByteSize(), true);
|
||||
nodeBuffer.Write(pDevice, 0, nodes.GetGlobalTransformByteSize(), nodes.GetGlobalTransformPtr());
|
||||
BufferHandle nodeHandle = m_ResourceManager->Commit(&nodeBuffer);
|
||||
|
||||
#pragma region Staging / Transfer / Uploads
|
||||
StorageBuffer positionBuffer;
|
||||
positionBuffer.Init(pDevice, vertexPositions.size() * sizeof vertexPositions[0], false);
|
||||
BufferHandle positionBufferHandle = m_ResourceManager->Commit(&positionBuffer);
|
||||
|
|
@ -595,48 +486,43 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
texCoord0BufferHandle = m_ResourceManager->Commit(&texCoord0Buffer);
|
||||
}
|
||||
|
||||
StorageBuffer color0Buffer;
|
||||
BufferHandle color0Handle;
|
||||
if (!color0.empty())
|
||||
{
|
||||
color0Buffer.Init(pDevice, color0.size() * sizeof color0[0], false);
|
||||
color0Handle = m_ResourceManager->Commit(&color0Buffer);
|
||||
}
|
||||
|
||||
IndexBuffer indexBuffer;
|
||||
indexBuffer.Init(pDevice, indices.size() * sizeof indices[0]);
|
||||
|
||||
{
|
||||
auto uploadBufferData = [cmd = this->m_CommandBuffer, &stagingBuffers, pDevice](const Buffer *buffer, void* data) {
|
||||
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = buffer->GetSize()};
|
||||
StagingBuffer &stagingBuffer = stagingBuffers.push_back();
|
||||
stagingBuffer.Init(pDevice, bufferCopy.size);
|
||||
stagingBuffer.Write(pDevice, 0, bufferCopy.size, data);
|
||||
cmd.copyBuffer(stagingBuffer.m_Buffer, buffer->m_Buffer, 1, &bufferCopy);
|
||||
};
|
||||
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0};
|
||||
|
||||
uploadBufferData(&positionBuffer, vertexPositions.data());
|
||||
bufferCopy.size = positionBuffer.GetSize();
|
||||
StagingBuffer &positionStaging = stagingBuffers.push_back();
|
||||
positionStaging.Init(pDevice, bufferCopy.size);
|
||||
positionStaging.Write(pDevice, 0, bufferCopy.size, vertexPositions.data());
|
||||
m_CommandBuffer.copyBuffer(positionStaging.m_Buffer, positionBuffer.m_Buffer, 1, &bufferCopy);
|
||||
|
||||
if (normalBuffer.IsValid())
|
||||
{
|
||||
uploadBufferData(&normalBuffer, normalVectors.data());
|
||||
bufferCopy.size = normalBuffer.GetSize();
|
||||
StagingBuffer &normalStaging = stagingBuffers.push_back();
|
||||
normalStaging.Init(pDevice, bufferCopy.size);
|
||||
normalStaging.Write(pDevice, 0, bufferCopy.size, normalVectors.data());
|
||||
m_CommandBuffer.copyBuffer(normalStaging.m_Buffer, normalBuffer.m_Buffer, 1, &bufferCopy);
|
||||
}
|
||||
|
||||
if (texCoord0Buffer.IsValid())
|
||||
{
|
||||
uploadBufferData(&texCoord0Buffer, texCoord0.data());
|
||||
bufferCopy.size = texCoord0Buffer.GetSize();
|
||||
StagingBuffer &textureStaging = stagingBuffers.push_back();
|
||||
textureStaging.Init(pDevice, bufferCopy.size);
|
||||
textureStaging.Write(pDevice, 0, bufferCopy.size, texCoord0.data());
|
||||
m_CommandBuffer.copyBuffer(textureStaging.m_Buffer, texCoord0Buffer.m_Buffer, 1, &bufferCopy);
|
||||
}
|
||||
|
||||
if (color0Buffer.IsValid())
|
||||
{
|
||||
uploadBufferData(&color0Buffer, color0.data());
|
||||
}
|
||||
|
||||
uploadBufferData(&indexBuffer, indices.data());
|
||||
bufferCopy.size = indexBuffer.GetSize();
|
||||
StagingBuffer &indexStaging = stagingBuffers.push_back();
|
||||
indexStaging.Init(pDevice, bufferCopy.size);
|
||||
indexStaging.Write(pDevice, 0, bufferCopy.size, indices.data());
|
||||
m_CommandBuffer.copyBuffer(indexStaging.m_Buffer, indexBuffer.m_Buffer, 1, &bufferCopy);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
AbortIfFailed(m_CommandBuffer.end());
|
||||
|
||||
vk::SubmitInfo submitInfo = {
|
||||
|
|
@ -661,26 +547,28 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched)
|
|||
buffer.Destroy(pDevice);
|
||||
}
|
||||
|
||||
nodes.Update();
|
||||
|
||||
return Model{m_ResourceManager, std::move(textureHandles), std::move(nodes),
|
||||
materialsHandle, positionBufferHandle, normalBufferHandle,
|
||||
texCoord0BufferHandle, color0Handle, indexBuffer, meshPrimitives, nodeHandle};
|
||||
return Model{m_ResourceManager, std::move(textures), std::move(textureHandles), materialsBuffer,
|
||||
materialsHandle, positionBuffer, positionBufferHandle, normalBuffer,
|
||||
normalBufferHandle, texCoord0Buffer, texCoord0BufferHandle, indexBuffer,
|
||||
meshPrimitives};
|
||||
}
|
||||
|
||||
Model::Model(GpuResourceManager *resourceManager, eastl::vector<TextureHandle> &&textureHandles, Nodes &&nodes,
|
||||
BufferHandle materialsHandle, BufferHandle vertexPosHandle, BufferHandle normalHandle,
|
||||
BufferHandle uv0Handle, BufferHandle vertexColor, const IndexBuffer &indexBuffer,
|
||||
const eastl::vector<MeshPrimitive> &meshPrimitives, BufferHandle nodeHandle)
|
||||
Model::Model(RenderResourceManager *resourceManager, eastl::vector<Texture> &&textures,
|
||||
eastl::vector<TextureHandle> &&textureHandles, const StorageBuffer &materialsBuffer,
|
||||
BufferHandle materialsHandle, const StorageBuffer &vertexPosBuffer, BufferHandle vertexPosHandle,
|
||||
const StorageBuffer &normalBuffer, BufferHandle normalHandle, const StorageBuffer &uv0Buffer,
|
||||
BufferHandle uv0Handle, const IndexBuffer &indexBuffer, const eastl::vector<MeshPrimitive> &meshPrimitives)
|
||||
: m_ResourceManager(resourceManager)
|
||||
, m_TextureHandles(std::move(textureHandles))
|
||||
, m_Nodes(std::move(nodes))
|
||||
, m_Textures(textures)
|
||||
, m_TextureHandles(textureHandles)
|
||||
, m_MaterialsBuffer(materialsBuffer)
|
||||
, m_MaterialsHandle(materialsHandle)
|
||||
, m_VertexPositions(vertexPosBuffer)
|
||||
, m_VertexPositionHandle(vertexPosHandle)
|
||||
, m_NormalVectors(normalBuffer)
|
||||
, m_NormalHandle(normalHandle)
|
||||
, m_TexCoord0(uv0Buffer)
|
||||
, m_TexCoord0Handle(uv0Handle)
|
||||
, m_VertexColorHandle(vertexColor)
|
||||
, m_NodeHandle(nodeHandle)
|
||||
, m_IndexBuffer(indexBuffer)
|
||||
, m_MeshPrimitives(meshPrimitives)
|
||||
{
|
||||
|
|
@ -688,13 +576,16 @@ Model::Model(GpuResourceManager *resourceManager, eastl::vector<TextureHandle> &
|
|||
|
||||
Model::Model(Model &&other) noexcept
|
||||
: m_ResourceManager(Take(other.m_ResourceManager))
|
||||
, m_Textures(std::move(other.m_Textures))
|
||||
, m_TextureHandles(std::move(other.m_TextureHandles))
|
||||
, m_MaterialsBuffer(other.m_MaterialsBuffer)
|
||||
, m_MaterialsHandle(other.m_MaterialsHandle)
|
||||
, m_VertexPositions(other.m_VertexPositions)
|
||||
, m_VertexPositionHandle(other.m_VertexPositionHandle)
|
||||
, m_NormalVectors(other.m_NormalVectors)
|
||||
, m_NormalHandle(other.m_NormalHandle)
|
||||
, m_TexCoord0(other.m_TexCoord0)
|
||||
, m_TexCoord0Handle(other.m_TexCoord0Handle)
|
||||
, m_VertexColorHandle(other.m_VertexColorHandle)
|
||||
, m_NodeHandle(other.m_NodeHandle)
|
||||
, m_IndexBuffer(other.m_IndexBuffer)
|
||||
, m_MeshPrimitives(std::move(other.m_MeshPrimitives))
|
||||
{
|
||||
|
|
@ -706,13 +597,16 @@ Model::operator=(Model &&other) noexcept
|
|||
if (this == &other)
|
||||
return *this;
|
||||
m_ResourceManager = Take(other.m_ResourceManager);
|
||||
m_Textures = std::move(other.m_Textures);
|
||||
m_TextureHandles = std::move(other.m_TextureHandles);
|
||||
m_MaterialsBuffer = other.m_MaterialsBuffer;
|
||||
m_MaterialsHandle = other.m_MaterialsHandle;
|
||||
m_VertexPositions = other.m_VertexPositions;
|
||||
m_VertexPositionHandle = other.m_VertexPositionHandle;
|
||||
m_NormalVectors = other.m_NormalVectors;
|
||||
m_NormalHandle = other.m_NormalHandle;
|
||||
m_TexCoord0 = other.m_TexCoord0;
|
||||
m_TexCoord0Handle = other.m_TexCoord0Handle;
|
||||
m_VertexColorHandle = other.m_VertexColorHandle;
|
||||
m_NodeHandle = std::move(other.m_NodeHandle);
|
||||
m_IndexBuffer = other.m_IndexBuffer;
|
||||
m_MeshPrimitives = std::move(other.m_MeshPrimitives);
|
||||
return *this;
|
||||
|
|
@ -723,9 +617,11 @@ Model::~Model()
|
|||
if (!m_ResourceManager)
|
||||
return;
|
||||
|
||||
m_VertexPositions.Destroy(m_ResourceManager->m_Device);
|
||||
m_IndexBuffer.Destroy(m_ResourceManager->m_Device);
|
||||
m_ResourceManager->Release(m_NodeHandle);
|
||||
m_ResourceManager->Release(m_VertexColorHandle);
|
||||
m_NormalVectors.Destroy(m_ResourceManager->m_Device);
|
||||
m_TexCoord0.Destroy(m_ResourceManager->m_Device);
|
||||
|
||||
m_ResourceManager->Release(m_VertexPositionHandle);
|
||||
m_ResourceManager->Release(m_NormalHandle);
|
||||
m_ResourceManager->Release(m_TexCoord0Handle);
|
||||
|
|
@ -734,14 +630,19 @@ Model::~Model()
|
|||
m_ResourceManager->Release(handle);
|
||||
}
|
||||
m_ResourceManager->Release(m_MaterialsHandle);
|
||||
for (Texture &texture : m_Textures)
|
||||
{
|
||||
texture.Destroy(m_ResourceManager->m_Device);
|
||||
}
|
||||
m_MaterialsBuffer.Destroy(m_ResourceManager->m_Device);
|
||||
}
|
||||
|
||||
ModelLoader::ModelLoader(GpuResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex,
|
||||
ModelLoader::ModelLoader(RenderResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex,
|
||||
u32 graphicsQueueIndex)
|
||||
: m_ResourceManager(resourceManager)
|
||||
, m_TransferQueue(transferQueue)
|
||||
, m_TransferQueueIndex(transferQueueIndex)
|
||||
, m_GraphicsQueueIndex(graphicsQueueIndex)
|
||||
, m_TransferQueue(transferQueue)
|
||||
, m_TransferQueueIndex(transferQueueIndex)
|
||||
, m_GraphicsQueueIndex(graphicsQueueIndex)
|
||||
{
|
||||
const Device *pDevice = resourceManager->m_Device;
|
||||
const vk::CommandPoolCreateInfo poolCreateInfo = {
|
||||
|
|
|
|||
|
|
@ -22,150 +22,53 @@ constexpr auto GLTF_BINARY_FILE_EXTENSION = ".glb";
|
|||
struct MeshPrimitive
|
||||
{
|
||||
u32 m_VertexOffset;
|
||||
i32 m_NormalOffset; // <0 for invalid
|
||||
i32 m_NormalOffset; // <0 for invalid
|
||||
i32 m_TexCoord0Offset; // <0 for invalid
|
||||
u32 m_FirstIndex;
|
||||
u32 m_IndexCount;
|
||||
i32 m_MaterialIdx; // <0 for invalid
|
||||
i32 m_TransformIdx;
|
||||
};
|
||||
|
||||
struct Nodes
|
||||
{
|
||||
eastl::vector<mat4> m_Transforms;
|
||||
eastl::vector<mat4> m_GlobalTransforms;
|
||||
eastl::vector<u32> m_Parents_;
|
||||
bool m_Dirty = true;
|
||||
|
||||
constexpr static u32 ROOT_BIT = 1u << 31;
|
||||
constexpr static u32 DIRTY_BIT = 1u << 30;
|
||||
constexpr static u32 PARENT_MASK = ~(ROOT_BIT | DIRTY_BIT);
|
||||
|
||||
u32
|
||||
Add(const mat4& transform, i32 parent = -1)
|
||||
{
|
||||
m_Dirty = true;
|
||||
u32 index = Count();
|
||||
m_Transforms.push_back(transform);
|
||||
m_GlobalTransforms.push_back(transform);
|
||||
const u32 parentVal = (parent < 0 ? ROOT_BIT : parent & PARENT_MASK) | DIRTY_BIT;
|
||||
m_Parents_.push_back(parentVal);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
[[nodiscard]] const mat4 &
|
||||
Get(const u32 index) const
|
||||
{
|
||||
return m_Transforms[index];
|
||||
}
|
||||
|
||||
void
|
||||
Set(const u32 index, const mat4 &transform)
|
||||
{
|
||||
m_Dirty = true;
|
||||
m_Transforms[index] = transform;
|
||||
m_Parents_[index] |= DIRTY_BIT;
|
||||
}
|
||||
|
||||
[[nodiscard]] const mat4 &
|
||||
operator[](const u32 index) const
|
||||
{
|
||||
return m_Transforms[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] mat4 &
|
||||
operator[](const u32 index)
|
||||
{
|
||||
m_Dirty = true;
|
||||
m_Parents_[index] |= DIRTY_BIT;
|
||||
return m_Transforms[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] u32
|
||||
Count() const
|
||||
{
|
||||
return Cast<u32>(m_Transforms.size());
|
||||
}
|
||||
|
||||
[[nodiscard]] usize
|
||||
GetGlobalTransformByteSize() const
|
||||
{
|
||||
return m_Transforms.size() * sizeof m_Transforms[0];
|
||||
}
|
||||
|
||||
[[nodiscard]] const mat4 *
|
||||
GetGlobalTransformPtr() const
|
||||
{
|
||||
return m_Transforms.data();
|
||||
}
|
||||
|
||||
void
|
||||
Update()
|
||||
{
|
||||
if (!m_Dirty)
|
||||
return;
|
||||
|
||||
auto transformIter = m_Transforms.begin();
|
||||
auto globalTransformIter = m_GlobalTransforms.begin();
|
||||
auto parentIter = m_Parents_.begin();
|
||||
const auto parentEnd = m_Parents_.end();
|
||||
|
||||
while (parentIter != parentEnd)
|
||||
{
|
||||
if (!(*parentIter & ROOT_BIT) && *parentIter & DIRTY_BIT)
|
||||
{
|
||||
u32 parent = *parentIter & PARENT_MASK;
|
||||
*globalTransformIter = m_GlobalTransforms[parent] * *transformIter;
|
||||
}
|
||||
else
|
||||
{
|
||||
*globalTransformIter = *transformIter;
|
||||
}
|
||||
*parentIter &= ~DIRTY_BIT;
|
||||
|
||||
++parentIter;
|
||||
++globalTransformIter;
|
||||
++transformIter;
|
||||
}
|
||||
|
||||
m_Dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct Material
|
||||
{
|
||||
vec4 m_AlbedoFactor; // 16 16
|
||||
vec3 m_EmissionFactor; // 12 28
|
||||
f32 m_MetalFactor; // 04 32
|
||||
f32 m_RoughFactor; // 04 36
|
||||
TextureHandle m_AlbedoTex; // 04 40
|
||||
TextureHandle m_NormalTex; // 04 44
|
||||
TextureHandle m_MetalRoughTex; // 04 48
|
||||
TextureHandle m_OcclusionTex; // 04 52
|
||||
TextureHandle m_EmissionTex; // 04 56
|
||||
vec4 m_AlbedoFactor;
|
||||
vec3 m_EmissionFactor;
|
||||
f32 m_MetalFactor;
|
||||
f32 m_RoughFactor;
|
||||
TextureHandle m_AlbedoTex;
|
||||
TextureHandle m_NormalTex;
|
||||
TextureHandle m_MetalRoughTex;
|
||||
TextureHandle m_OcclusionTex;
|
||||
TextureHandle m_EmissionTex;
|
||||
};
|
||||
|
||||
struct Model
|
||||
{
|
||||
GpuResourceManager *m_ResourceManager;
|
||||
RenderResourceManager *m_ResourceManager;
|
||||
|
||||
eastl::vector<Texture> m_Textures;
|
||||
eastl::vector<TextureHandle> m_TextureHandles;
|
||||
Nodes m_Nodes;
|
||||
|
||||
StorageBuffer m_MaterialsBuffer;
|
||||
BufferHandle m_MaterialsHandle;
|
||||
|
||||
StorageBuffer m_VertexPositions;
|
||||
BufferHandle m_VertexPositionHandle;
|
||||
|
||||
StorageBuffer m_NormalVectors;
|
||||
BufferHandle m_NormalHandle;
|
||||
|
||||
StorageBuffer m_TexCoord0;
|
||||
BufferHandle m_TexCoord0Handle;
|
||||
BufferHandle m_VertexColorHandle;
|
||||
BufferHandle m_NodeHandle;
|
||||
|
||||
IndexBuffer m_IndexBuffer;
|
||||
eastl::vector<MeshPrimitive> m_MeshPrimitives;
|
||||
|
||||
Model(GpuResourceManager *resourceManager, eastl::vector<TextureHandle> &&textureHandles, Nodes&& nodes,
|
||||
BufferHandle materialsHandle, BufferHandle vertexPosHandle, BufferHandle normalHandle, BufferHandle uv0Handle, BufferHandle vertexColor,
|
||||
const IndexBuffer &indexBuffer, const eastl::vector<MeshPrimitive> &meshPrimitives, BufferHandle nodeHandle);
|
||||
Model(RenderResourceManager *resourceManager, eastl::vector<Texture> &&textures,
|
||||
eastl::vector<TextureHandle> &&textureHandles, const StorageBuffer &materialsBuffer,
|
||||
BufferHandle materialsHandle, const StorageBuffer &vertexPosBuffer, BufferHandle vertexPosHandle,
|
||||
const StorageBuffer &normalBuffer, BufferHandle normalHandle, const StorageBuffer &uv0Buffer,
|
||||
BufferHandle uv0Handle, const IndexBuffer &indexBuffer, const eastl::vector<MeshPrimitive> &meshPrimitives);
|
||||
|
||||
Model(Model &&other) noexcept;
|
||||
Model &operator=(Model &&other) noexcept;
|
||||
|
|
@ -177,18 +80,18 @@ struct Model
|
|||
|
||||
struct ModelLoader
|
||||
{
|
||||
GpuResourceManager *m_ResourceManager;
|
||||
RenderResourceManager *const m_ResourceManager;
|
||||
vk::CommandPool m_CommandPool;
|
||||
vk::CommandBuffer m_CommandBuffer;
|
||||
vk::Queue m_TransferQueue;
|
||||
u32 m_TransferQueueIndex;
|
||||
u32 m_GraphicsQueueIndex;
|
||||
|
||||
ModelLoader(GpuResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex,
|
||||
ModelLoader(RenderResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex,
|
||||
u32 graphicsQueueIndex);
|
||||
~ModelLoader();
|
||||
|
||||
TextureHandle LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBuffer,
|
||||
TextureHandle LoadImage(vk::CommandBuffer commandBuffer, Texture *texture, StagingBuffer *stagingBuffer,
|
||||
tinygltf::Image *image) const;
|
||||
Model LoadModel(cstr path, cstr name = nullptr, bool batched = false);
|
||||
|
||||
|
|
@ -197,7 +100,6 @@ struct ModelLoader
|
|||
constexpr static auto ATangent = "TANGENT";
|
||||
constexpr static auto ATexCoord0 = "TEXCOORD_0";
|
||||
constexpr static auto ATexCoord1 = "TEXCOORD_1";
|
||||
constexpr static auto AColor0 = "COLOR_0";
|
||||
constexpr static auto AJoints0 = "JOINTS_0";
|
||||
constexpr static auto AWeights0 = "WEIGHTS_0";
|
||||
};
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
#include <filesystem>
|
||||
|
||||
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
||||
constexpr auto MODEL_FILE = "model/OrientationTest.glb";
|
||||
constexpr auto MODEL_FILE = "model/BoxTextured.glb";
|
||||
|
||||
struct ImageFile
|
||||
{
|
||||
|
|
@ -85,7 +85,7 @@ main(int, char **)
|
|||
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
|
||||
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
||||
Swapchain swapchain = {&window, &device, "Primary Chain"};
|
||||
GpuResourceManager resourceManager = {&device, 1000};
|
||||
RenderResourceManager resourceManager = {&device, 1000};
|
||||
|
||||
ModelLoader modelLoader = {&resourceManager, commandQueue, queueAllocation.m_Family, queueAllocation.m_Family};
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ main(int, char **)
|
|||
|
||||
Camera camera = {
|
||||
.m_Model = {1.0f},
|
||||
.m_View = glm::lookAt(vec3(0.0f, 12.0f, 12.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)),
|
||||
.m_Perspective = glm::perspective(
|
||||
70_deg, Cast<f32>(swapchain.m_Extent.width) / Cast<f32>(swapchain.m_Extent.height), 0.1f, 100.0f),
|
||||
};
|
||||
|
|
@ -217,18 +217,14 @@ main(int, char **)
|
|||
struct ModelData
|
||||
{
|
||||
BufferHandle m_VertexBuffer;
|
||||
BufferHandle m_Color;
|
||||
BufferHandle m_UvBuffer;
|
||||
BufferHandle m_Materials;
|
||||
BufferHandle m_Nodes;
|
||||
};
|
||||
|
||||
ModelData modelData = {
|
||||
.m_VertexBuffer = model.m_VertexPositionHandle,
|
||||
.m_Color = model.m_VertexColorHandle,
|
||||
.m_UvBuffer = model.m_TexCoord0Handle,
|
||||
.m_Materials = model.m_MaterialsHandle,
|
||||
.m_Nodes = model.m_NodeHandle,
|
||||
};
|
||||
|
||||
INFO("Starting loop");
|
||||
|
|
@ -299,10 +295,7 @@ main(int, char **)
|
|||
|
||||
for (auto &prim : model.m_MeshPrimitives)
|
||||
{
|
||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof modelData,
|
||||
sizeof prim.m_MaterialIdx, &prim.m_MaterialIdx);
|
||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof modelData + sizeof prim.m_MaterialIdx,
|
||||
sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
|
||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof modelData, sizeof prim, &prim);
|
||||
cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast<i32>(prim.m_VertexOffset), 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include <EASTL/array.h>
|
||||
|
||||
Pipeline
|
||||
CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResourceManager *resourceManager)
|
||||
CreatePipeline(const Device *device, const Swapchain *swapchain, const RenderResourceManager *resourceManager)
|
||||
{
|
||||
// Pipeline Setup
|
||||
auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE);
|
||||
|
|
@ -58,7 +58,7 @@ CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResour
|
|||
vk::PushConstantRange pushConstantRange = {
|
||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||
.offset = 0,
|
||||
.size = 28,
|
||||
.size = 36,
|
||||
};
|
||||
|
||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "global.h"
|
||||
#include "pipeline.h"
|
||||
|
||||
struct GpuResourceManager;
|
||||
struct RenderResourceManager;
|
||||
struct Swapchain;
|
||||
struct Device;
|
||||
|
||||
|
|
@ -22,4 +22,4 @@ struct Vertex
|
|||
};
|
||||
|
||||
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
|
||||
Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResourceManager *resourceManager);
|
||||
Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain, const RenderResourceManager *resourceManager);
|
||||
|
|
|
|||
|
|
@ -12,184 +12,25 @@
|
|||
|
||||
#include <EASTL/array.h>
|
||||
|
||||
void
|
||||
TextureManager::Init(const u32 maxCapacity)
|
||||
{
|
||||
m_MaxCapacity = maxCapacity;
|
||||
m_FreeHead = GpuResourceHandle::INVALID_HANDLE;
|
||||
}
|
||||
|
||||
TextureHandle
|
||||
TextureManager::Commit(Texture *texture)
|
||||
{
|
||||
ERROR_IF(!texture->IsValid() || !texture->IsOwned(), "Buffer must be valid and owned for commital")
|
||||
THEN_ABORT(-1);
|
||||
|
||||
if (m_FreeHead != GpuResourceHandle::INVALID_HANDLE)
|
||||
{
|
||||
const u32 index = m_FreeHead;
|
||||
|
||||
Texture *allocatedTexture = &m_Textures[index];
|
||||
|
||||
assert(!allocatedTexture->IsValid());
|
||||
m_FreeHead = *Recast<u32 *>(allocatedTexture);
|
||||
|
||||
// Ensure it is copyable.
|
||||
static_assert(std::is_trivially_copyable_v<Texture>);
|
||||
memcpy(allocatedTexture, texture, sizeof *texture);
|
||||
|
||||
// Take ownership of the buffer.
|
||||
texture->m_MipLevels_ &= ~Texture::OWNED_BIT;
|
||||
|
||||
return {index};
|
||||
}
|
||||
|
||||
const u32 index = Cast<u32>(m_Textures.size());
|
||||
if (index < m_MaxCapacity)
|
||||
{
|
||||
Texture *allocatedTexture = &m_Textures.push_back();
|
||||
|
||||
// Ensure it is copyable.
|
||||
static_assert(std::is_trivially_copyable_v<Texture>);
|
||||
memcpy(allocatedTexture, texture, sizeof *texture);
|
||||
|
||||
texture->m_MipLevels_ &= ~Texture::OWNED_BIT;
|
||||
|
||||
return {index};
|
||||
}
|
||||
|
||||
ERROR("Out of Buffers") THEN_ABORT(-1);
|
||||
}
|
||||
|
||||
Texture *
|
||||
TextureManager::Fetch(const TextureHandle handle)
|
||||
{
|
||||
assert(!handle.IsInvalid());
|
||||
|
||||
return &m_Textures[handle.m_Index];
|
||||
}
|
||||
|
||||
void
|
||||
TextureManager::Release(const Device *device, const TextureHandle handle)
|
||||
{
|
||||
assert(!handle.IsInvalid());
|
||||
|
||||
Texture *allocatedTexture = &m_Textures[handle.m_Index];
|
||||
allocatedTexture->Destroy(device);
|
||||
|
||||
assert(!allocatedTexture->IsValid());
|
||||
*Recast<u32 *>(allocatedTexture) = m_FreeHead;
|
||||
|
||||
m_FreeHead = handle.m_Index;
|
||||
}
|
||||
|
||||
void
|
||||
TextureManager::Destroy(const Device *device)
|
||||
{
|
||||
for (auto &texture : m_Textures)
|
||||
{
|
||||
texture.Destroy(device);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BufferManager::Init(const u32 maxCapacity)
|
||||
{
|
||||
m_MaxCapacity = maxCapacity;
|
||||
m_FreeHead = GpuResourceHandle::INVALID_HANDLE;
|
||||
}
|
||||
|
||||
BufferHandle
|
||||
BufferManager::Commit(StorageBuffer *buffer)
|
||||
{
|
||||
ERROR_IF(!buffer->IsValid() || !buffer->IsOwned(), "Buffer must be valid and owned for commital") THEN_ABORT(-1);
|
||||
|
||||
if (m_FreeHead != GpuResourceHandle::INVALID_HANDLE)
|
||||
{
|
||||
const u32 index = m_FreeHead;
|
||||
|
||||
StorageBuffer *allocatedBuffer = &m_Buffers[index];
|
||||
|
||||
assert(!allocatedBuffer->IsValid());
|
||||
m_FreeHead = *Recast<u32 *>(allocatedBuffer);
|
||||
|
||||
// Ensure it is copyable.
|
||||
static_assert(std::is_trivially_copyable_v<StorageBuffer>);
|
||||
memcpy(allocatedBuffer, buffer, sizeof *buffer);
|
||||
|
||||
// Take ownership of the buffer.
|
||||
buffer->m_Size_ &= ~StorageBuffer::OWNED_BIT;
|
||||
|
||||
return {index};
|
||||
}
|
||||
|
||||
const u32 index = Cast<u32>(m_Buffers.size());
|
||||
if (index < m_MaxCapacity)
|
||||
{
|
||||
StorageBuffer *allocatedBuffer = &m_Buffers.push_back();
|
||||
|
||||
// Ensure it is copyable.
|
||||
static_assert(std::is_trivially_copyable_v<StorageBuffer>);
|
||||
memcpy(allocatedBuffer, buffer, sizeof *buffer);
|
||||
|
||||
buffer->m_Size_ &= ~StorageBuffer::OWNED_BIT;
|
||||
|
||||
return {index};
|
||||
}
|
||||
|
||||
ERROR("Out of Buffers") THEN_ABORT(-1);
|
||||
}
|
||||
|
||||
StorageBuffer *
|
||||
BufferManager::Fetch(const BufferHandle handle)
|
||||
{
|
||||
assert(!handle.IsInvalid());
|
||||
|
||||
return &m_Buffers[handle.m_Index];
|
||||
}
|
||||
|
||||
void
|
||||
BufferManager::Release(const Device *device, const BufferHandle handle)
|
||||
{
|
||||
assert(!handle.IsInvalid());
|
||||
|
||||
StorageBuffer *allocatedBuffer = &m_Buffers[handle.m_Index];
|
||||
allocatedBuffer->Destroy(device);
|
||||
|
||||
assert(!allocatedBuffer->IsValid());
|
||||
*Recast<u32 *>(allocatedBuffer) = m_FreeHead;
|
||||
|
||||
m_FreeHead = handle.m_Index;
|
||||
}
|
||||
|
||||
void
|
||||
BufferManager::Destroy(const Device *device)
|
||||
{
|
||||
for (auto& buffer : m_Buffers)
|
||||
{
|
||||
buffer.Destroy(device);
|
||||
}
|
||||
}
|
||||
|
||||
GpuResourceManager::WriteInfo::WriteInfo(vk::DescriptorBufferInfo info)
|
||||
RenderResourceManager::WriteInfo::WriteInfo(vk::DescriptorBufferInfo info)
|
||||
: uBufferInfo(info)
|
||||
{
|
||||
}
|
||||
|
||||
GpuResourceManager::WriteInfo::WriteInfo(vk::DescriptorImageInfo info)
|
||||
RenderResourceManager::WriteInfo::WriteInfo(vk::DescriptorImageInfo info)
|
||||
: uImageInfo(info)
|
||||
{
|
||||
}
|
||||
|
||||
GpuResourceManager::WriteInfo::WriteInfo(vk::BufferView info)
|
||||
RenderResourceManager::WriteInfo::WriteInfo(vk::BufferView info)
|
||||
: uBufferView(info)
|
||||
{
|
||||
}
|
||||
|
||||
BufferHandle
|
||||
GpuResourceManager::Commit(StorageBuffer *storageBuffer)
|
||||
RenderResourceManager::Commit(const StorageBuffer *storageBuffer)
|
||||
{
|
||||
const BufferHandle handle = m_BufferManager.Commit(storageBuffer);
|
||||
const u32 handle = m_BufferFreeList.Alloc();
|
||||
|
||||
m_WriteInfos.emplace_back(vk::DescriptorBufferInfo{
|
||||
.buffer = storageBuffer->m_Buffer,
|
||||
|
|
@ -200,23 +41,19 @@ GpuResourceManager::Commit(StorageBuffer *storageBuffer)
|
|||
m_Writes.push_back({
|
||||
.dstSet = m_DescriptorSet,
|
||||
.dstBinding = BUFFER_BINDING_INDEX,
|
||||
.dstArrayElement = handle.m_Index,
|
||||
.dstArrayElement = handle,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||
.pBufferInfo = &m_WriteInfos.back().uBufferInfo,
|
||||
});
|
||||
|
||||
m_WriteOwner.emplace_back(HandleType::eBuffer, handle.m_Index);
|
||||
m_WriteOwner.emplace_back(HandleType::eBuffer, handle);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
++m_CommitedBufferCount;
|
||||
#endif
|
||||
|
||||
return handle;
|
||||
return {handle};
|
||||
}
|
||||
|
||||
void
|
||||
GpuResourceManager::EraseWrites(u32 handleIndex, HandleType handleType)
|
||||
RenderResourceManager::EraseWrites(u32 handleIndex, HandleType handleType)
|
||||
{
|
||||
auto writeIter = m_Writes.begin();
|
||||
auto ownerIter = m_WriteOwner.begin();
|
||||
|
|
@ -239,39 +76,31 @@ GpuResourceManager::EraseWrites(u32 handleIndex, HandleType handleType)
|
|||
}
|
||||
|
||||
void
|
||||
GpuResourceManager::Release(BufferHandle handle)
|
||||
RenderResourceManager::Release(BufferHandle handle)
|
||||
{
|
||||
if (handle.IsInvalid())
|
||||
return;
|
||||
|
||||
EraseWrites(handle.m_Index, HandleType::eBuffer);
|
||||
|
||||
m_BufferManager.Release(m_Device, handle);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
--m_CommitedBufferCount;
|
||||
#endif
|
||||
m_BufferFreeList.Free(handle.m_Index);
|
||||
}
|
||||
|
||||
void
|
||||
GpuResourceManager::Release(TextureHandle handle)
|
||||
RenderResourceManager::Release(TextureHandle handle)
|
||||
{
|
||||
if (handle.IsInvalid())
|
||||
return;
|
||||
|
||||
EraseWrites(handle.m_Index, HandleType::eTexture);
|
||||
|
||||
m_TextureManager.Release(m_Device, handle);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
--m_CommitedTextureCount;
|
||||
#endif
|
||||
m_TextureFreeList.Free(handle.m_Index);
|
||||
}
|
||||
|
||||
TextureHandle
|
||||
GpuResourceManager::Commit(Texture* texture)
|
||||
RenderResourceManager::Commit(const Texture *texture)
|
||||
{
|
||||
TextureHandle handle = m_TextureManager.Commit(texture);
|
||||
const u32 handle = m_TextureFreeList.Alloc();
|
||||
|
||||
m_WriteInfos.emplace_back(vk::DescriptorImageInfo{
|
||||
.sampler = nullptr,
|
||||
|
|
@ -282,23 +111,19 @@ GpuResourceManager::Commit(Texture* texture)
|
|||
m_Writes.push_back({
|
||||
.dstSet = m_DescriptorSet,
|
||||
.dstBinding = TEXTURE_BINDING_INDEX,
|
||||
.dstArrayElement = handle.m_Index,
|
||||
.dstArrayElement = handle,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||
.pImageInfo = &m_WriteInfos.back().uImageInfo,
|
||||
});
|
||||
|
||||
m_WriteOwner.emplace_back(HandleType::eBuffer, handle.m_Index);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
++m_CommitedTextureCount;
|
||||
#endif
|
||||
m_WriteOwner.emplace_back(HandleType::eBuffer, handle);
|
||||
|
||||
return {handle};
|
||||
}
|
||||
|
||||
void
|
||||
GpuResourceManager::Update()
|
||||
RenderResourceManager::Update()
|
||||
{
|
||||
if (m_Writes.empty() || m_WriteInfos.empty())
|
||||
return;
|
||||
|
|
@ -310,7 +135,7 @@ GpuResourceManager::Update()
|
|||
m_WriteOwner.clear();
|
||||
}
|
||||
|
||||
GpuResourceManager::GpuResourceManager(const Device *device, u16 maxSize)
|
||||
RenderResourceManager::RenderResourceManager(const Device *device, u16 maxSize)
|
||||
: m_Device(device)
|
||||
{
|
||||
vk::PhysicalDeviceProperties properties;
|
||||
|
|
@ -341,8 +166,8 @@ GpuResourceManager::GpuResourceManager(const Device *device, u16 maxSize)
|
|||
INFO("Max Buffer Count: {}", buffersCount);
|
||||
INFO("Max Texture Count: {}", texturesCount);
|
||||
|
||||
m_BufferManager.Init(buffersCount);
|
||||
m_TextureManager.Init(texturesCount);
|
||||
m_BufferFreeList.Init(buffersCount);
|
||||
m_TextureFreeList.Init(texturesCount);
|
||||
|
||||
eastl::array poolSizes = {
|
||||
vk::DescriptorPoolSize{
|
||||
|
|
@ -400,54 +225,9 @@ GpuResourceManager::GpuResourceManager(const Device *device, u16 maxSize)
|
|||
m_Device->SetName(m_DescriptorSet, "Bindless Set");
|
||||
}
|
||||
|
||||
GpuResourceManager::~GpuResourceManager()
|
||||
RenderResourceManager::~RenderResourceManager()
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
WARN_IF(m_CommitedBufferCount > 0 || m_CommitedTextureCount > 0, "Resources alive: SSBO = {}, Textures = {}",
|
||||
m_CommitedBufferCount, m_CommitedTextureCount);
|
||||
#endif
|
||||
|
||||
m_BufferManager.Destroy(m_Device);
|
||||
m_Device->m_Device.destroy(m_Sampler, nullptr);
|
||||
m_Device->m_Device.destroy(m_DescriptorPool, nullptr);
|
||||
m_Device->m_Device.destroy(m_SetLayout, nullptr);
|
||||
}
|
||||
|
||||
GpuResourceManager::GpuResourceManager(GpuResourceManager &&other) noexcept
|
||||
: m_WriteInfos(std::move(other.m_WriteInfos)),
|
||||
m_Writes(std::move(other.m_Writes)),
|
||||
m_WriteOwner(std::move(other.m_WriteOwner)),
|
||||
m_Sampler(other.m_Sampler),
|
||||
m_BufferManager(std::move(other.m_BufferManager)),
|
||||
m_TextureManager(std::move(other.m_TextureManager)),
|
||||
m_Device(Take(other.m_Device)),
|
||||
m_DescriptorPool(other.m_DescriptorPool),
|
||||
m_SetLayout(other.m_SetLayout),
|
||||
m_DescriptorSet(other.m_DescriptorSet),
|
||||
m_CommitedBufferCount(other.m_CommitedBufferCount),
|
||||
m_CommitedTextureCount(other.m_CommitedTextureCount)
|
||||
{
|
||||
assert(!other.m_Device);
|
||||
}
|
||||
|
||||
GpuResourceManager &
|
||||
GpuResourceManager::operator=(GpuResourceManager &&other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
m_WriteInfos = std::move(other.m_WriteInfos);
|
||||
m_Writes = std::move(other.m_Writes);
|
||||
m_WriteOwner = std::move(other.m_WriteOwner);
|
||||
m_Sampler = other.m_Sampler;
|
||||
m_BufferManager = std::move(other.m_BufferManager);
|
||||
m_TextureManager = std::move(other.m_TextureManager);
|
||||
m_Device = Take(other.m_Device); // Ensure taken.
|
||||
m_DescriptorPool = other.m_DescriptorPool;
|
||||
m_SetLayout = other.m_SetLayout;
|
||||
m_DescriptorSet = other.m_DescriptorSet;
|
||||
m_CommitedBufferCount = other.m_CommitedBufferCount;
|
||||
m_CommitedTextureCount = other.m_CommitedTextureCount;
|
||||
|
||||
assert(!other.m_Device);
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -5,9 +5,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "global.h"
|
||||
#include "buffer.h"
|
||||
#include "image.h"
|
||||
#include "global.h"
|
||||
|
||||
#include <EASTL/deque.h>
|
||||
#include <EASTL/stack.h>
|
||||
|
|
@ -17,7 +16,7 @@ struct Device;
|
|||
struct Texture;
|
||||
struct UniformStorageBuffer;
|
||||
|
||||
struct GpuResourceManager;
|
||||
struct RenderResourceManager;
|
||||
|
||||
struct GpuResourceHandle
|
||||
{
|
||||
|
|
@ -39,46 +38,54 @@ struct TextureHandle : GpuResourceHandle
|
|||
{
|
||||
};
|
||||
|
||||
struct TextureManager
|
||||
struct FreeList
|
||||
{
|
||||
eastl::vector<Texture> m_Textures;
|
||||
u32 m_MaxCapacity;
|
||||
u32 m_FreeHead;
|
||||
eastl::stack<u32, eastl::deque<u32>> m_List;
|
||||
u32 m_MaxVisited = 0;
|
||||
u32 m_MaxCapacity = 16;
|
||||
|
||||
void
|
||||
Init(u32 maxCapacity);
|
||||
TextureHandle Commit(Texture *texture);
|
||||
Texture *Fetch(TextureHandle handle);
|
||||
void Release(const Device *device, TextureHandle handle);
|
||||
void Destroy(const Device *device);
|
||||
};
|
||||
|
||||
struct BufferManager
|
||||
{
|
||||
eastl::vector<StorageBuffer> m_Buffers;
|
||||
u32 m_MaxCapacity;
|
||||
u32 m_FreeHead;
|
||||
|
||||
void Init(u32 maxCapacity);
|
||||
BufferHandle Commit(StorageBuffer *buffer);
|
||||
StorageBuffer *Fetch(BufferHandle handle);
|
||||
void Release(const Device *device, BufferHandle handle);
|
||||
void Destroy(const Device *device);
|
||||
};
|
||||
|
||||
struct GpuResourceManager
|
||||
{
|
||||
private:
|
||||
union WriteInfo
|
||||
Init(u32 maxCapacity)
|
||||
{
|
||||
// MaxValue<u32> is 'invalid-handle' so you can't use it as a handle.
|
||||
assert(maxCapacity < GpuResourceHandle::INVALID_HANDLE);
|
||||
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
|
||||
{
|
||||
private:
|
||||
union WriteInfo {
|
||||
vk::DescriptorBufferInfo uBufferInfo;
|
||||
vk::DescriptorImageInfo uImageInfo;
|
||||
vk::BufferView uBufferView;
|
||||
|
||||
WriteInfo()
|
||||
{
|
||||
}
|
||||
|
||||
explicit WriteInfo(vk::DescriptorBufferInfo info);
|
||||
explicit WriteInfo(vk::DescriptorImageInfo info);
|
||||
explicit WriteInfo(vk::BufferView info);
|
||||
|
|
@ -98,13 +105,12 @@ private:
|
|||
|
||||
vk::Sampler m_Sampler;
|
||||
|
||||
//FreeList m_BufferFreeList;
|
||||
BufferManager m_BufferManager;
|
||||
TextureManager m_TextureManager;
|
||||
FreeList m_BufferFreeList;
|
||||
FreeList m_TextureFreeList;
|
||||
|
||||
void EraseWrites(u32 handleIndex, HandleType handleType);
|
||||
|
||||
public:
|
||||
public:
|
||||
const Device *m_Device;
|
||||
|
||||
constexpr static u32 BUFFER_BINDING_INDEX = 0;
|
||||
|
|
@ -114,24 +120,16 @@ public:
|
|||
vk::DescriptorSetLayout m_SetLayout;
|
||||
vk::DescriptorSet m_DescriptorSet;
|
||||
|
||||
BufferHandle Commit(StorageBuffer *storageBuffer);
|
||||
BufferHandle Commit(const StorageBuffer *storageBuffer);
|
||||
void Release(BufferHandle handle);
|
||||
TextureHandle Commit(Texture *texture);
|
||||
TextureHandle Commit(const Texture *texture);
|
||||
void Release(TextureHandle handle);
|
||||
|
||||
void Update();
|
||||
|
||||
// Ctor/Dtor
|
||||
GpuResourceManager(const Device *device, u16 maxSize);
|
||||
~GpuResourceManager();
|
||||
RenderResourceManager(const Device *device, u16 maxSize);
|
||||
~RenderResourceManager();
|
||||
|
||||
GpuResourceManager(GpuResourceManager &&other) noexcept;
|
||||
GpuResourceManager &operator=(GpuResourceManager &&other) noexcept;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
usize m_CommitedBufferCount = 0;
|
||||
usize m_CommitedTextureCount = 0;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GpuResourceManager);
|
||||
DISALLOW_COPY_AND_ASSIGN(RenderResourceManager);
|
||||
};
|
||||
|
|
@ -2,17 +2,11 @@
|
|||
typedef float4 PositionData;
|
||||
typedef float2 UVData;
|
||||
typedef float4 NormalData;
|
||||
typedef float4 ColorData;
|
||||
|
||||
struct TransformData
|
||||
{
|
||||
float4x4 transform;
|
||||
};
|
||||
|
||||
struct MaterialData
|
||||
{
|
||||
float m_AlbedoFactor[4];
|
||||
float m_EmissionFactor[3];
|
||||
float4 m_AlbedoFactor;
|
||||
float3 m_EmissionFactor;
|
||||
float m_MetalFactor;
|
||||
float m_RoughFactor;
|
||||
uint m_AlbedoTex;
|
||||
|
|
@ -25,19 +19,21 @@ struct MaterialData
|
|||
struct Block
|
||||
{
|
||||
uint vertexBufferHandle;
|
||||
uint colorHandle;
|
||||
uint uvBufferHandle;
|
||||
uint materialBufferHandle;
|
||||
uint nodeBufferHandle;
|
||||
uint m_VertexOffset;
|
||||
int m_NormalOffset;
|
||||
int m_TexCoord0Offset;
|
||||
uint m_FirstIndex;
|
||||
uint m_IndexCount;
|
||||
int m_MaterialIdx;
|
||||
uint m_NodeIdx;
|
||||
};
|
||||
|
||||
struct Camera
|
||||
{
|
||||
float4x4 model;
|
||||
float4x4 view;
|
||||
float4x4 proj;
|
||||
row_major float4x4 model;
|
||||
row_major float4x4 view;
|
||||
row_major float4x4 proj;
|
||||
};
|
||||
|
||||
#define INVALID_HANDLE 0xFFFFFFFF
|
||||
|
|
@ -45,9 +41,7 @@ struct Camera
|
|||
[[vk::binding(0, 0)]] StructuredBuffer<PositionData> vertexBuffer[];
|
||||
[[vk::binding(0, 0)]] StructuredBuffer<UVData> uvBuffer[];
|
||||
[[vk::binding(0, 0)]] StructuredBuffer<NormalData> normalBuffer[];
|
||||
[[vk::binding(0, 0)]] StructuredBuffer<ColorData> colorBuffer[];
|
||||
[[vk::binding(0, 0)]] StructuredBuffer<MaterialData> materialsBuffer[];
|
||||
[[vk::binding(0, 0)]] StructuredBuffer<TransformData> nodeBuffer[];
|
||||
|
||||
[[vk::binding(1, 0)]] Texture2D<float4> textures[];
|
||||
[[vk::binding(1, 0)]] SamplerState immutableSamplers[];
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
struct FS_Input
|
||||
{
|
||||
float4 inPosition : POSITION;
|
||||
float4 inColor : COLOR0;
|
||||
float2 inUV : TEXCOORD0;
|
||||
};
|
||||
|
||||
|
|
@ -12,27 +10,35 @@ struct FS_Output
|
|||
float4 outColor : SV_Target0;
|
||||
};
|
||||
|
||||
float4 ArrayToVector(float arr[4])
|
||||
struct Float4
|
||||
{
|
||||
return float4(arr[0], arr[1], arr[2], arr[3]);
|
||||
}
|
||||
float4 value;
|
||||
};
|
||||
|
||||
float4 GetAlbedo(uint materialBufferId, int materialId, float2 uv)
|
||||
float4 GetAlbedo(uint materialBufferId, int materialId, float2 uv0)
|
||||
{
|
||||
uint albedoTexId = materialsBuffer[materialBufferId][materialId].m_AlbedoTex;
|
||||
if (albedoTexId == INVALID_HANDLE)
|
||||
if (materialId < 0)
|
||||
{
|
||||
return ArrayToVector(materialsBuffer[materialBufferId][materialId].m_AlbedoFactor);
|
||||
return float4(1.0f, 0.0f, 1.0f, 1.0f); // Magenta
|
||||
}
|
||||
else
|
||||
{
|
||||
return textures[albedoTexId].Sample(immutableSamplers[albedoTexId], uv);
|
||||
float4 albedoFactor = materialsBuffer[materialBufferId][materialId].m_AlbedoFactor;
|
||||
uint albedoTexId = materialsBuffer[materialBufferId][materialId].m_AlbedoTex;
|
||||
if (albedoTexId == INVALID_HANDLE)
|
||||
{
|
||||
return albedoFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
return textures[albedoTexId].Sample(immutableSamplers[albedoTexId], uv0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FS_Output main(FS_Input stage_input)
|
||||
{
|
||||
FS_Output output;
|
||||
output.outColor = pcb.m_MaterialIdx < 0 ? stage_input.inColor : GetAlbedo(pcb.materialBufferHandle, pcb.m_MaterialIdx, stage_input.inUV);
|
||||
return output;
|
||||
FS_Output stage_output;
|
||||
stage_output.outColor = GetAlbedo(pcb.materialBufferHandle, pcb.m_MaterialIdx, stage_input.inUV);
|
||||
return stage_output;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ struct VS_Input
|
|||
|
||||
struct VS_Output
|
||||
{
|
||||
float4 outPosition : POSITION;
|
||||
float4 outColor : COLOR0;
|
||||
float2 outUV : TEXCOORD0;
|
||||
UVData outUV : TEXCOORD0;
|
||||
float4 position : SV_Position;
|
||||
};
|
||||
|
||||
|
|
@ -25,30 +23,15 @@ float2 GetUV(uint bufferId, uint vertexIdx)
|
|||
}
|
||||
}
|
||||
|
||||
float4 GetPosition(uint bufferId, uint vertexIdx)
|
||||
float3 GetPosition(uint bufferId, uint vertexIdx)
|
||||
{
|
||||
return float4(vertexBuffer[bufferId][vertexIdx].xyz, 1.0f);
|
||||
}
|
||||
|
||||
float4 GetColor(uint bufferId, uint vertexIdx)
|
||||
{
|
||||
return (bufferId != INVALID_HANDLE) ? colorBuffer[bufferId][vertexIdx] : float4(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
float4x4 GetModel(uint bufferId, uint index)
|
||||
{
|
||||
return nodeBuffer[bufferId][index].transform;
|
||||
return vertexBuffer[bufferId][vertexIdx].xyz;
|
||||
}
|
||||
|
||||
VS_Output main(VS_Input stage_input)
|
||||
{
|
||||
VS_Output output;
|
||||
output.outPosition = GetPosition(pcb.vertexBufferHandle, stage_input.vertexIndex);
|
||||
output.outUV = GetUV(pcb.uvBufferHandle, stage_input.vertexIndex);
|
||||
output.outColor = GetColor(pcb.colorHandle, stage_input.vertexIndex);
|
||||
|
||||
float4 globalPosition = mul(camera.model, mul(GetModel(pcb.nodeBufferHandle, pcb.m_NodeIdx), GetPosition(pcb.vertexBufferHandle, stage_input.vertexIndex)));
|
||||
float4 clipSpace = mul(camera.view, globalPosition);
|
||||
output.position = mul(camera.proj, clipSpace);
|
||||
return output;
|
||||
VS_Output stage_output;
|
||||
stage_output.outUV = GetUV(pcb.uvBufferHandle, stage_input.vertexIndex);
|
||||
stage_output.position = mul(float4(GetPosition(pcb.vertexBufferHandle, stage_input.vertexIndex), 1.0f), mul(camera.model, mul(camera.view, camera.proj)));
|
||||
return stage_output;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue