diff --git a/samples/03_model_render/CMakeLists.txt b/samples/03_model_render/CMakeLists.txt index 82653d9..38492a7 100644 --- a/samples/03_model_render/CMakeLists.txt +++ b/samples/03_model_render/CMakeLists.txt @@ -13,8 +13,6 @@ add_executable(model_render model_render.cpp model_loader.cpp model_loader.h ) -add_shader(model_render shader/model.vert.glsl) -add_shader(model_render shader/model.frag.glsl) add_shader(model_render shader/model.vs.hlsl) add_shader(model_render shader/model.ps.hlsl) diff --git a/samples/03_model_render/model_loader.cpp b/samples/03_model_render/model_loader.cpp index ad8de08..7748c33 100644 --- a/samples/03_model_render/model_loader.cpp +++ b/samples/03_model_render/model_loader.cpp @@ -291,9 +291,7 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) // TODO: Support scenes eastl::vector vertexPositions; - eastl::vector normalVectors; - eastl::vector texCoord0; - eastl::vector color0; + eastl::vector vertexData; eastl::vector indices; eastl::vector meshPrimitives; meshPrimitives.reserve(model.meshes.size()); @@ -303,9 +301,6 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) meshPrimRanges.reserve(model.meshes.size()); u32 vertexOffset = 0; - u32 normalOffset = 0; - u32 texCoord0Offset = 0; - u32 color0Offset = 0; u32 indexOffset = 0; for (auto &mesh : model.meshes) @@ -315,9 +310,6 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) { u32 vertexCount = 0; u32 indexCount = 0; - u32 normalCount = 0; - u32 texCoord0Count = 0; - u32 color0Count = 0; #pragma region Position assert(prim.attributes.contains(APosition)); @@ -357,7 +349,10 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) } } #pragma endregion -#pragma region Normal + + vertexData.resize(vertexPositions.size()); + + #pragma region Normal // Normal Coords if (prim.attributes.contains(ANormal)) { @@ -369,20 +364,25 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) tinygltf::Buffer *normBuffer = &model.buffers[normBufferView->buffer]; usize byteOffset = (normAccessor->byteOffset + normBufferView->byteOffset); - normalCount = Cast(normAccessor->count); - normalVectors.reserve(vertexPositions.size()); - if (normAccessor->type == TINYGLTF_TYPE_VEC4) { vec4 *data = Recast(normBuffer->data.data() + byteOffset); - normalVectors.insert(normalVectors.end(), data, data + vertexCount); + + vec4 *end = data + vertexCount; + u32 idx = vertexOffset; + vec4 *it = data; + while (it != end) + { + vertexData[idx++].m_Normal = *(it++); + } } else if (normAccessor->type == TINYGLTF_TYPE_VEC3) { vec3 *data = Recast(normBuffer->data.data() + byteOffset); for (u32 i = 0; i < vertexCount; ++i) { - normalVectors.push_back(vec4(data[i], 1.0f)); + auto norm = vec4(data[i], 0.0f); + vertexData[vertexOffset + i].m_Normal = norm; } } else if (normAccessor->type == TINYGLTF_TYPE_VEC2) @@ -390,7 +390,8 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) vec2 *data = Recast(normBuffer->data.data() + byteOffset); for (u32 i = 0; i < vertexCount; ++i) { - normalVectors.push_back(vec4(data[i], 0.0f, 1.0f)); + auto norm = vec4(data[i], 0.0f, 0.0f); + vertexData[vertexOffset + i].m_Normal = norm; } } } @@ -407,14 +408,17 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) tinygltf::Buffer *uvBuffer = &model.buffers[uvBufferView->buffer]; usize byteOffset = (uvAccessor->byteOffset + uvBufferView->byteOffset); - texCoord0Count = Cast(uvAccessor->count); - texCoord0.reserve(vertexPositions.size()); - assert(uvAccessor->type == TINYGLTF_TYPE_VEC2 && uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT); { vec2 *data = Recast(uvBuffer->data.data() + byteOffset); - texCoord0.insert(texCoord0.end(), data, data + vertexCount); + vec2 *end = data + vertexCount; + u32 idx = vertexOffset; + vec2 *it = data; + while (it != end) + { + vertexData[idx++].m_TexCoord0 = *(it++); + } } } #pragma endregion @@ -429,21 +433,25 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) tinygltf::Buffer *colorBuffer = &model.buffers[colorBufferView->buffer]; usize byteOffset = (colorAccessor->byteOffset + colorBufferView->byteOffset); - color0Count = Cast(colorAccessor->count); - color0.reserve(vertexPositions.size()); - assert(color0Count == vertexCount); - if (colorAccessor->type == TINYGLTF_TYPE_VEC4) { vec4 *data = Recast(colorBuffer->data.data() + byteOffset); - color0.insert(color0.end(), data, data + vertexCount); + + vec4 *end = data + vertexCount; + u32 idx = vertexOffset; + vec4 *it = data; + while (it != end) + { + vertexData[idx++].m_Color0 = *(it++); + } } else if (colorAccessor->type == TINYGLTF_TYPE_VEC3) { vec3 *data = Recast(colorBuffer->data.data() + byteOffset); - for (u32 i = 0; i < color0Count; ++i) + for (u32 i = 0; i < vertexCount; ++i) { - color0.push_back(vec4(data[i], 1.0f)); + auto color = vec4(data[i], 1.0f); + vertexData[vertexOffset + i].m_Color0 = color; } } } @@ -492,9 +500,6 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) meshPrimitives.push_back({ .m_VertexOffset = vertexOffset, - .m_NormalOffset = normalCount > 0 ? Cast(normalOffset) : -1, - .m_TexCoord0Offset = texCoord0Count > 0 ? Cast(texCoord0Offset) : -1, - // TODO: Color offset .m_FirstIndex = indexOffset, .m_IndexCount = indexCount, .m_MaterialIdx = prim.material, @@ -503,12 +508,6 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) vertexOffset += vertexCount; indexOffset += indexCount; - texCoord0Offset += texCoord0Count; - normalOffset += normalCount; - color0Offset += color0Count; - - assert(normalVectors.empty() || normalVectors.size() == vertexPositions.size()); - assert(texCoord0.empty() || texCoord0.size() == vertexPositions.size()); } } @@ -576,39 +575,13 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) 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); - - StorageBuffer normalBuffer; - BufferHandle normalBufferHandle; - if (!normalVectors.empty()) - { - normalBuffer.Init(pDevice, normalVectors.size() * sizeof normalVectors[0], false); - normalBufferHandle = m_ResourceManager->Commit(&normalBuffer); - } - - StorageBuffer texCoord0Buffer; - BufferHandle texCoord0BufferHandle; - if (!texCoord0.empty()) - { - texCoord0Buffer.Init(pDevice, texCoord0.size() * sizeof texCoord0[0], false); - 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); - } - + BufferHandle positionBufferHandle; + BufferHandle vertexDataHandle; IndexBuffer indexBuffer; - indexBuffer.Init(pDevice, indices.size() * sizeof indices[0]); { - auto uploadBufferData = [cmd = this->m_CommandBuffer, &stagingBuffers, pDevice](const Buffer *buffer, void* data) { + auto uploadBufferData = [cmd = this->m_CommandBuffer, &stagingBuffers, pDevice](const Buffer *buffer, + const void *data) { vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = buffer->GetSize()}; StagingBuffer &stagingBuffer = stagingBuffers.push_back(); stagingBuffer.Init(pDevice, bufferCopy.size); @@ -616,23 +589,17 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) cmd.copyBuffer(stagingBuffer.m_Buffer, buffer->m_Buffer, 1, &bufferCopy); }; + StorageBuffer positionBuffer; + positionBuffer.Init(pDevice, vertexPositions.size() * sizeof vertexPositions[0], false); + positionBufferHandle = m_ResourceManager->Commit(&positionBuffer); uploadBufferData(&positionBuffer, vertexPositions.data()); - if (normalBuffer.IsValid()) - { - uploadBufferData(&normalBuffer, normalVectors.data()); - } - - if (texCoord0Buffer.IsValid()) - { - uploadBufferData(&texCoord0Buffer, texCoord0.data()); - } - - if (color0Buffer.IsValid()) - { - uploadBufferData(&color0Buffer, color0.data()); - } + StorageBuffer vertexDataBuffer; + vertexDataBuffer.Init(pDevice, vertexData.size() * sizeof vertexData[0], false); + vertexDataHandle = m_ResourceManager->Commit(&vertexDataBuffer); + uploadBufferData(&vertexDataBuffer, vertexData.data()); + indexBuffer.Init(pDevice, indices.size() * sizeof indices[0]); uploadBufferData(&indexBuffer, indices.data()); } @@ -662,24 +629,23 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) buffer.Destroy(pDevice); } + Model::ModelHandles handles = { + .m_VertexPositionHandle = positionBufferHandle, + .m_VertexDataHandle = vertexDataHandle, + .m_MaterialsHandle = materialsHandle, + .m_NodeHandle = nodeHandle, + }; + return Model{m_ResourceManager, std::move(textureHandles), std::move(nodes), - materialsHandle, positionBufferHandle, normalBufferHandle, - texCoord0BufferHandle, color0Handle, indexBuffer, meshPrimitives, nodeHandle}; + handles, indexBuffer, meshPrimitives, }; } Model::Model(GpuResourceManager *resourceManager, eastl::vector &&textureHandles, Nodes &&nodes, - BufferHandle materialsHandle, BufferHandle vertexPosHandle, BufferHandle normalHandle, - BufferHandle uv0Handle, BufferHandle vertexColor, const IndexBuffer &indexBuffer, - const eastl::vector &meshPrimitives, BufferHandle nodeHandle) + const ModelHandles &handles, const IndexBuffer &indexBuffer, const eastl::vector &meshPrimitives) : m_ResourceManager(resourceManager) , m_TextureHandles(std::move(textureHandles)) , m_Nodes(std::move(nodes)) - , m_MaterialsHandle(materialsHandle) - , m_VertexPositionHandle(vertexPosHandle) - , m_NormalHandle(normalHandle) - , m_TexCoord0Handle(uv0Handle) - , m_VertexColorHandle(vertexColor) - , m_NodeHandle(nodeHandle) + , m_Handles(handles) , m_IndexBuffer(indexBuffer) , m_MeshPrimitives(meshPrimitives) { @@ -688,12 +654,7 @@ Model::Model(GpuResourceManager *resourceManager, eastl::vector & Model::Model(Model &&other) noexcept : m_ResourceManager(Take(other.m_ResourceManager)) , m_TextureHandles(std::move(other.m_TextureHandles)) - , m_MaterialsHandle(other.m_MaterialsHandle) - , m_VertexPositionHandle(other.m_VertexPositionHandle) - , m_NormalHandle(other.m_NormalHandle) - , m_TexCoord0Handle(other.m_TexCoord0Handle) - , m_VertexColorHandle(other.m_VertexColorHandle) - , m_NodeHandle(other.m_NodeHandle) + , m_Handles(other.m_Handles) , m_IndexBuffer(other.m_IndexBuffer) , m_MeshPrimitives(std::move(other.m_MeshPrimitives)) { @@ -706,17 +667,121 @@ Model::operator=(Model &&other) noexcept return *this; m_ResourceManager = Take(other.m_ResourceManager); m_TextureHandles = std::move(other.m_TextureHandles); - m_MaterialsHandle = other.m_MaterialsHandle; - m_VertexPositionHandle = other.m_VertexPositionHandle; - m_NormalHandle = other.m_NormalHandle; - m_TexCoord0Handle = other.m_TexCoord0Handle; - m_VertexColorHandle = other.m_VertexColorHandle; - m_NodeHandle = other.m_NodeHandle; + m_Handles = other.m_Handles; m_IndexBuffer = other.m_IndexBuffer; m_MeshPrimitives = std::move(other.m_MeshPrimitives); return *this; } +u32 +Nodes::Add(const mat4 &transform, const i32 parent) +{ + m_Dirty = true; + const 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; +} + +const mat4 & +Nodes::Get(const u32 index) const +{ + return m_Transforms[index]; +} + +void +Nodes::Set(const u32 index, const mat4 &transform) +{ + m_Dirty = true; + m_Transforms[index] = transform; + m_Parents_[index] |= DIRTY_BIT; +} + +const mat4 & +Nodes::operator[](const u32 index) const +{ + return m_Transforms[index]; +} + +mat4 & +Nodes::operator[](const u32 index) +{ + m_Dirty = true; + m_Parents_[index] |= DIRTY_BIT; + return m_Transforms[index]; +} + +u32 +Nodes::Count() const +{ + return Cast(m_Transforms.size()); +} + +usize +Nodes::GetGlobalTransformByteSize() const +{ + return m_GlobalTransforms.size() * sizeof m_GlobalTransforms[0]; +} + +const mat4 * +Nodes::GetGlobalTransformPtr() const +{ + return m_GlobalTransforms.data(); +} + +bool +Nodes::Update() +{ + if (!m_Dirty) + return false; + + auto transformIter = m_Transforms.begin(); + auto globalTransformIter = m_GlobalTransforms.begin(); + auto parentIter = m_Parents_.begin(); + const auto parentEnd = m_Parents_.end(); + + while (parentIter != parentEnd) + { + const bool isRoot = *parentIter & ROOT_BIT; + const bool isDirty = *parentIter & DIRTY_BIT; + + if (isRoot) + { + if (isDirty) + { + // Copy-update if the root is dirty. + *globalTransformIter = *transformIter; + } + } + else + { + const u32 parentIdx = *parentIter & PARENT_MASK; + const bool isParentDirty = m_Parents_[parentIdx] & DIRTY_BIT; + if (isDirty || isParentDirty) + { + // Update w.r.t parent if either local or parent transforms updated. + *globalTransformIter = m_GlobalTransforms[parentIdx] * *transformIter; + m_Parents_[parentIdx] |= DIRTY_BIT; // Set dirty to propagate the update. + } + } + + ++parentIter; + ++globalTransformIter; + ++transformIter; + } + + for (u32 &parentValue : m_Parents_) + { + parentValue &= ~DIRTY_BIT; // Unset dirty. + } + + m_Dirty = false; + return true; +} + const mat4 & Model::GetModelTransform() const { @@ -735,16 +800,16 @@ Model::~Model() return; m_IndexBuffer.Destroy(m_ResourceManager->m_Device); - m_ResourceManager->Release(m_NodeHandle); - m_ResourceManager->Release(m_VertexColorHandle); - m_ResourceManager->Release(m_VertexPositionHandle); - m_ResourceManager->Release(m_NormalHandle); - m_ResourceManager->Release(m_TexCoord0Handle); + + m_ResourceManager->Release(m_Handles.m_VertexDataHandle); + m_ResourceManager->Release(m_Handles.m_NodeHandle); + m_ResourceManager->Release(m_Handles.m_VertexPositionHandle); + m_ResourceManager->Release(m_Handles.m_MaterialsHandle); + for (const TextureHandle &handle : m_TextureHandles) { m_ResourceManager->Release(handle); } - m_ResourceManager->Release(m_MaterialsHandle); } void @@ -752,7 +817,7 @@ Model::Update() { if (m_Nodes.Update()) { - m_ResourceManager->Write(m_NodeHandle, 0, m_Nodes.GetGlobalTransformByteSize(), + m_ResourceManager->Write(m_Handles.m_NodeHandle, 0, m_Nodes.GetGlobalTransformByteSize(), m_Nodes.GetGlobalTransformPtr()); } } @@ -782,5 +847,31 @@ ModelLoader::ModelLoader(GpuResourceManager *resourceManager, vk::Queue transfer ModelLoader::~ModelLoader() { - m_ResourceManager->m_Device->m_Device.destroy(m_CommandPool, nullptr); + if (m_ResourceManager) + { + m_ResourceManager->m_Device->m_Device.destroy(m_CommandPool, nullptr); + } +} + +ModelLoader::ModelLoader(ModelLoader &&other) noexcept: m_ResourceManager(Take(other.m_ResourceManager)), + m_CommandPool(other.m_CommandPool), + m_CommandBuffer(other.m_CommandBuffer), + m_TransferQueue(other.m_TransferQueue), + m_TransferQueueIndex(other.m_TransferQueueIndex), + m_GraphicsQueueIndex(other.m_GraphicsQueueIndex) +{ +} + +ModelLoader & +ModelLoader::operator=(ModelLoader &&other) noexcept +{ + if (this == &other) + return *this; + m_ResourceManager = Take(other.m_ResourceManager); + m_CommandPool = other.m_CommandPool; + m_CommandBuffer = other.m_CommandBuffer; + m_TransferQueue = other.m_TransferQueue; + m_TransferQueueIndex = other.m_TransferQueueIndex; + m_GraphicsQueueIndex = other.m_GraphicsQueueIndex; + return *this; } \ No newline at end of file diff --git a/samples/03_model_render/model_loader.h b/samples/03_model_render/model_loader.h index 25ac8a4..6ab9dfe 100644 --- a/samples/03_model_render/model_loader.h +++ b/samples/03_model_render/model_loader.h @@ -21,8 +21,6 @@ constexpr auto GLTF_BINARY_FILE_EXTENSION = ".glb"; struct MeshPrimitive { u32 m_VertexOffset; - i32 m_NormalOffset; // <0 for invalid - i32 m_TexCoord0Offset; // <0 for invalid u32 m_FirstIndex; u32 m_IndexCount; i32 m_MaterialIdx; // <0 for invalid @@ -41,114 +39,18 @@ struct Nodes constexpr static u32 DIRTY_BIT = 1u << 30; constexpr static u32 PARENT_MASK = ~(ROOT_BIT | DIRTY_BIT); - u32 - Add(const mat4& transform, const i32 parent = -1) - { - m_Dirty = true; - const 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); + u32 Add(const mat4 &transform, const i32 parent = -1); + [[nodiscard]] const mat4 &Get(const u32 index) const; + void Set(const u32 index, const mat4 &transform); + [[nodiscard]] u32 Count() const; - return index; - } + [[nodiscard]] const mat4 &operator[](const u32 index) const; + [[nodiscard]] mat4 &operator[](const u32 index); - [[nodiscard]] const mat4 & - Get(const u32 index) const - { - return m_Transforms[index]; - } + [[nodiscard]] usize GetGlobalTransformByteSize() const; + [[nodiscard]] const mat4 *GetGlobalTransformPtr() const; - 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(m_Transforms.size()); - } - - [[nodiscard]] usize - GetGlobalTransformByteSize() const - { - return m_GlobalTransforms.size() * sizeof m_GlobalTransforms[0]; - } - - [[nodiscard]] const mat4 * - GetGlobalTransformPtr() const - { - return m_GlobalTransforms.data(); - } - - bool - Update() - { - if (!m_Dirty) - return false; - - auto transformIter = m_Transforms.begin(); - auto globalTransformIter = m_GlobalTransforms.begin(); - auto parentIter = m_Parents_.begin(); - const auto parentEnd = m_Parents_.end(); - - while (parentIter != parentEnd) - { - const bool isRoot = *parentIter & ROOT_BIT; - const bool isDirty = *parentIter & DIRTY_BIT; - - if (isRoot) - { - if (isDirty) - { - // Copy-update if the root is dirty. - *globalTransformIter = *transformIter; - } - } - else - { - const u32 parentIdx = *parentIter & PARENT_MASK; - const bool isParentDirty = m_Parents_[parentIdx] & DIRTY_BIT; - if (isDirty || isParentDirty) - { - // Update w.r.t parent if either local or parent transforms updated. - *globalTransformIter = m_GlobalTransforms[parentIdx] * *transformIter; - m_Parents_[parentIdx] |= DIRTY_BIT; // Set dirty to propagate the update. - } - } - - ++parentIter; - ++globalTransformIter; - ++transformIter; - } - - for (u32 &parentValue : m_Parents_) - { - parentValue &= ~DIRTY_BIT; // Unset dirty. - } - - m_Dirty = false; - return true; - } + bool Update(); }; struct Material @@ -164,6 +66,14 @@ struct Material TextureHandle m_EmissionTex; // 04 56 }; +struct VertexData +{ + vec4 m_Normal; + vec2 m_TexCoord0 = vec2{0.0f, 0.0f}; + vec2 m_TexCoord1 = vec2{0.0f, 0.0f}; + vec4 m_Color0 = vec4{1.0f, 0.0f, 1.0f, 1.0f}; +}; + struct Model { GpuResourceManager *m_ResourceManager; @@ -171,12 +81,13 @@ struct Model eastl::vector m_TextureHandles; Nodes m_Nodes; - BufferHandle m_MaterialsHandle; - BufferHandle m_VertexPositionHandle; - BufferHandle m_NormalHandle; - BufferHandle m_TexCoord0Handle; - BufferHandle m_VertexColorHandle; - BufferHandle m_NodeHandle; + struct ModelHandles + { + BufferHandle m_VertexPositionHandle; + BufferHandle m_VertexDataHandle; + BufferHandle m_MaterialsHandle; + BufferHandle m_NodeHandle; + } m_Handles; IndexBuffer m_IndexBuffer; eastl::vector m_MeshPrimitives; @@ -185,15 +96,15 @@ struct Model void SetModelTransform(const mat4 &transform); void Update(); - Model(GpuResourceManager *resourceManager, eastl::vector &&textureHandles, Nodes&& nodes, - BufferHandle materialsHandle, BufferHandle vertexPosHandle, BufferHandle normalHandle, BufferHandle uv0Handle, BufferHandle vertexColor, - const IndexBuffer &indexBuffer, const eastl::vector &meshPrimitives, BufferHandle nodeHandle); + Model(GpuResourceManager *resourceManager, eastl::vector &&textureHandles, Nodes &&nodes, + const ModelHandles& handles, const IndexBuffer &indexBuffer, const eastl::vector &meshPrimitives); + ~Model(); Model(Model &&other) noexcept; Model &operator=(Model &&other) noexcept; - ~Model(); - DISALLOW_COPY_AND_ASSIGN(Model); + Model(const Model &) = delete; + const Model &operator=(const Model &) = delete; }; struct ModelLoader @@ -205,10 +116,6 @@ struct ModelLoader u32 m_TransferQueueIndex; u32 m_GraphicsQueueIndex; - ModelLoader(GpuResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex, - u32 graphicsQueueIndex); - ~ModelLoader(); - TextureHandle LoadImage(vk::CommandBuffer commandBuffer, StagingBuffer *stagingBuffer, tinygltf::Image *image) const; Model LoadModel(cstr path, cstr name = nullptr, bool batched = false); @@ -221,4 +128,13 @@ struct ModelLoader constexpr static auto AColor0 = "COLOR_0"; constexpr static auto AJoints0 = "JOINTS_0"; constexpr static auto AWeights0 = "WEIGHTS_0"; + + ModelLoader(GpuResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex, + u32 graphicsQueueIndex); + ~ModelLoader(); + + ModelLoader(ModelLoader &&other) noexcept; + ModelLoader &operator=(ModelLoader &&other) noexcept; + + DISALLOW_COPY_AND_ASSIGN(ModelLoader); }; \ No newline at end of file diff --git a/samples/03_model_render/model_render.cpp b/samples/03_model_render/model_render.cpp index b894d71..d5880c7 100644 --- a/samples/03_model_render/model_render.cpp +++ b/samples/03_model_render/model_render.cpp @@ -66,18 +66,18 @@ main(int, char **) Features enabledDeviceFeatures = { .m_Vulkan10Features = {.samplerAnisotropy = 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, - }, + { + .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}, }; @@ -214,23 +214,6 @@ main(int, char **) Time::Init(); - 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"); while (window.Poll()) { @@ -297,13 +280,15 @@ main(int, char **) cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 1, 1, &descriptorSet, 0, nullptr); cmd.bindIndexBuffer(model.m_IndexBuffer.m_Buffer, 0, vk::IndexType::eUint32); - cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, 0, sizeof modelData, &modelData); + cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, 0, sizeof model.m_Handles, + &model.m_Handles); for (auto &prim : model.m_MeshPrimitives) { - cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof modelData, + cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof model.m_Handles, sizeof prim.m_MaterialIdx, &prim.m_MaterialIdx); - cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, sizeof modelData + sizeof prim.m_MaterialIdx, + cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, + sizeof model.m_Handles + sizeof prim.m_MaterialIdx, sizeof prim.m_TransformIdx, &prim.m_TransformIdx); cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast(prim.m_VertexOffset), 0); } @@ -402,4 +387,4 @@ ImageFile::~ImageFile() stbi_image_free(m_Data); } m_Data = nullptr; -} +} \ No newline at end of file diff --git a/samples/03_model_render/pipeline_utils.cpp b/samples/03_model_render/pipeline_utils.cpp index 250a489..5c84431 100644 --- a/samples/03_model_render/pipeline_utils.cpp +++ b/samples/03_model_render/pipeline_utils.cpp @@ -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 = 24, }; vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = { diff --git a/samples/03_model_render/pipeline_utils.h b/samples/03_model_render/pipeline_utils.h index c4f9161..47c40cf 100644 --- a/samples/03_model_render/pipeline_utils.h +++ b/samples/03_model_render/pipeline_utils.h @@ -15,11 +15,5 @@ struct Device; constexpr auto VERTEX_SHADER_FILE = "shader/model.vs.hlsl.spv"; constexpr auto FRAGMENT_SHADER_FILE = "shader/model.ps.hlsl.spv"; -struct Vertex -{ - vec3 m_Position; - vec2 m_TexCoord0; -}; - vk::ShaderModule CreateShader(const Device *device, cstr shaderFile); Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResourceManager *resourceManager); diff --git a/samples/03_model_render/render_resource_manager.cpp b/samples/03_model_render/render_resource_manager.cpp index a91035d..96cc30a 100644 --- a/samples/03_model_render/render_resource_manager.cpp +++ b/samples/03_model_render/render_resource_manager.cpp @@ -342,7 +342,7 @@ GpuResourceManager::GpuResourceManager(const Device *device, u16 maxSize) .borderColor = vk::BorderColor::eFloatOpaqueBlack, .unnormalizedCoordinates = false, }; - AbortIfFailed(device->m_Device.createSampler(&samplerCreateInfo, nullptr, &m_Sampler)); + AbortIfFailed(device->m_Device.createSampler(&samplerCreateInfo, nullptr, &m_ImmutableSampler)); INFO("Max Buffer Count: {}", buffersCount); INFO("Max Texture Count: {}", texturesCount); @@ -368,7 +368,7 @@ GpuResourceManager::GpuResourceManager(const Device *device, u16 maxSize) }; AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool)); - eastl::vector immutableSamplers(texturesCount, m_Sampler); + eastl::vector immutableSamplers(texturesCount, m_ImmutableSampler); eastl::array descriptorLayoutBindings = { vk::DescriptorSetLayoutBinding{ .binding = BUFFER_BINDING_INDEX, @@ -414,7 +414,7 @@ GpuResourceManager::~GpuResourceManager() #endif m_BufferManager.Destroy(m_Device); - m_Device->m_Device.destroy(m_Sampler, nullptr); + m_Device->m_Device.destroy(m_ImmutableSampler, nullptr); m_Device->m_Device.destroy(m_DescriptorPool, nullptr); m_Device->m_Device.destroy(m_SetLayout, nullptr); } @@ -423,7 +423,7 @@ 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_ImmutableSampler(other.m_ImmutableSampler), m_BufferManager(std::move(other.m_BufferManager)), m_TextureManager(std::move(other.m_TextureManager)), m_Device(Take(other.m_Device)), @@ -444,7 +444,7 @@ GpuResourceManager::operator=(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_ImmutableSampler = other.m_ImmutableSampler; m_BufferManager = std::move(other.m_BufferManager); m_TextureManager = std::move(other.m_TextureManager); m_Device = Take(other.m_Device); // Ensure taken. diff --git a/samples/03_model_render/render_resource_manager.h b/samples/03_model_render/render_resource_manager.h index f1e999b..5fb224c 100644 --- a/samples/03_model_render/render_resource_manager.h +++ b/samples/03_model_render/render_resource_manager.h @@ -10,15 +10,12 @@ #include "image.h" #include -#include #include struct Device; struct Texture; struct UniformStorageBuffer; -struct GpuResourceManager; - struct GpuResourceHandle { constexpr static u32 INVALID_HANDLE = MaxValue; @@ -96,9 +93,8 @@ private: eastl::vector m_Writes; eastl::vector m_WriteOwner; - vk::Sampler m_Sampler; + vk::Sampler m_ImmutableSampler; - //FreeList m_BufferFreeList; BufferManager m_BufferManager; TextureManager m_TextureManager; diff --git a/samples/03_model_render/shader/bindless_structs.hlsli b/samples/03_model_render/shader/bindless_structs.hlsli index c426566..4f4a5b0 100644 --- a/samples/03_model_render/shader/bindless_structs.hlsli +++ b/samples/03_model_render/shader/bindless_structs.hlsli @@ -4,6 +4,14 @@ typedef float2 UVData; typedef float4 NormalData; typedef float4 ColorData; +struct VertexData +{ + float4 m_Normal; + float2 m_TexCoord0; + float2 m_TexCoord1; + float4 m_Color0; +}; + struct TransformData { float4x4 transform; @@ -25,8 +33,7 @@ struct MaterialData struct Block { uint vertexBufferHandle; - uint colorHandle; - uint uvBufferHandle; + uint vertexDataHandle; uint materialBufferHandle; uint nodeBufferHandle; int m_MaterialIdx; @@ -43,9 +50,7 @@ struct Camera #define INVALID_HANDLE 0xFFFFFFFF [[vk::binding(0, 0)]] StructuredBuffer vertexBuffer[]; -[[vk::binding(0, 0)]] StructuredBuffer uvBuffer[]; -[[vk::binding(0, 0)]] StructuredBuffer normalBuffer[]; -[[vk::binding(0, 0)]] StructuredBuffer colorBuffer[]; +[[vk::binding(0, 0)]] StructuredBuffer vertexDataBuffer[]; [[vk::binding(0, 0)]] StructuredBuffer materialsBuffer[]; [[vk::binding(0, 0)]] StructuredBuffer nodeBuffer[]; diff --git a/samples/03_model_render/shader/model.frag.glsl b/samples/03_model_render/shader/model.frag.glsl deleted file mode 100644 index 2b1cacd..0000000 --- a/samples/03_model_render/shader/model.frag.glsl +++ /dev/null @@ -1,67 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) -#extension GL_EXT_nonuniform_qualifier : enable - -layout (location = 0) in vec2 inUV; -layout (location = 0) out vec4 outColor; - -struct VertexData { - float position[4]; -}; - -struct MaterialData { - float m_AlbedoFactor[4]; - float m_EmissionFactor[3]; - float m_MetalFactor; - float m_RoughFactor; - uint m_AlbedoTex; - uint m_NormalTex; - uint m_MetalRoughTex; - uint m_OcclusionTex; - uint m_EmissionTex; -}; - -#define INVALID_HANDLE 0xFFFFFFFF - -layout(set = 0, binding = 1) uniform sampler2D textures[]; -layout(std430, set = 0, binding = 0) readonly buffer Vertices { - VertexData data[]; -} vertexBuffer[]; -layout(std430, set = 0, binding = 0) readonly buffer Materials { - MaterialData data[]; -} materialsBuffer[]; - - -layout(push_constant) uniform Block { - uint vertexBufferHandle; - uint uvBufferHandle; - uint materialBufferHandle; - uint m_VertexOffset; - int m_NormalOffset; // <0 for invalid - int m_TexCoord0Offset; // <0 for invalid - uint m_FirstIndex; - uint m_IndexCount; - int m_MaterialIdx; // <0 for invalid -} pcb; - -vec4 ToVec4(float array[4]) { - return vec4(array[0], array[1], array[2], array[3]); -} - -vec4 GetAlbedo(uint materialBufferId, int materialId, vec2 uv0) { - if (materialId < 0) { - return vec4(1.0f, 0.0f, 1.0f, 1.0f); - } else { - vec4 albedoFactor = ToVec4(materialsBuffer[materialBufferId].data[materialId].m_AlbedoFactor); - uint albedoTexId = materialsBuffer[materialBufferId].data[materialId].m_AlbedoTex; - if (albedoTexId == INVALID_HANDLE) { - return albedoFactor; - } else { - return texture(textures[albedoTexId], uv0); - } - } -} - -void main() { - outColor = GetAlbedo(pcb.materialBufferHandle, pcb.m_MaterialIdx, inUV);// texture(textures[materialsBuffer[pcb.materialBufferHandle].data[pcb.m_MaterialIdx].m_AlbedoTex], inUV);// ToVec4(materialsBuffer[pcb.materialBufferHandle].data[pcb.m_MaterialIdx].m_AlbedoFactor);// vec4(texture(textures[textureHandle], inUV).rgb, 1.0f); -} \ No newline at end of file diff --git a/samples/03_model_render/shader/model.vert.glsl b/samples/03_model_render/shader/model.vert.glsl deleted file mode 100644 index ff38ca0..0000000 --- a/samples/03_model_render/shader/model.vert.glsl +++ /dev/null @@ -1,84 +0,0 @@ -#version 460 core -#pragma shader_stage(vertex) -#extension GL_EXT_nonuniform_qualifier : enable - -layout(location = 0) out vec2 outUV; - -struct Position { - float position[4]; -}; -struct Normal { - float normal[4]; -}; -struct UV { - float uv[2]; -}; - -struct MaterialData { - float m_AlbedoFactor[4]; - float m_EmissionFactor[3]; - float m_MetalFactor; - float m_RoughFactor; - uint m_AlbedoTex; - uint m_NormalTex; - uint m_MetalRoughTex; - uint m_OcclusionTex; - uint m_EmissionTex; -}; - -#define INVALID_HANDLE 0xFFFFFFFF - -layout(std430, set = 0, binding = 0) readonly buffer Vertices { - Position data[]; -} vertexBuffer[]; -layout(std430, set = 0, binding = 0) readonly buffer Normals { - Normal data[]; -} normalBuffer[]; -layout(std430, set = 0, binding = 0) readonly buffer TexCoord0 { - UV data[]; -} uvBuffer[]; -layout(std430, set = 0, binding = 0) readonly buffer Materials { - MaterialData data[]; -} materialsBuffer[]; - -vec3 GetPosition(uint bufferId, uint vertexIdx) { - return vec3( - vertexBuffer[bufferId].data[vertexIdx].position[0], - vertexBuffer[bufferId].data[vertexIdx].position[1], - vertexBuffer[bufferId].data[vertexIdx].position[2] - ); -} - -vec2 GetUV(uint bufferId, uint vertexIdx) { - if (bufferId == INVALID_HANDLE) { - return vec2(0.0f, 0.0f); - } else { - return vec2( - uvBuffer[bufferId].data[vertexIdx].uv[0], - uvBuffer[bufferId].data[vertexIdx].uv[1] - ); - } -} - -layout(set = 1, binding = 0) uniform Camera { - mat4 model; - mat4 view; - mat4 proj; -} ubo; - -layout(push_constant) uniform Block { - uint vertexBufferHandle; - uint uvBufferHandle; - uint materialBufferHandle; - uint m_VertexOffset; - int m_NormalOffset; // <0 for invalid - int m_TexCoord0Offset; // <0 for invalid - uint m_FirstIndex; - uint m_IndexCount; - int m_MaterialIdx; // <0 for invalid -} pcb; - -void main() { - outUV = GetUV(pcb.uvBufferHandle, gl_VertexIndex); - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(GetPosition(pcb.vertexBufferHandle, gl_VertexIndex), 1.0f); -} \ No newline at end of file diff --git a/samples/03_model_render/shader/model.vs.hlsl b/samples/03_model_render/shader/model.vs.hlsl index ffea9ec..2de5a59 100644 --- a/samples/03_model_render/shader/model.vs.hlsl +++ b/samples/03_model_render/shader/model.vs.hlsl @@ -15,14 +15,7 @@ struct VS_Output float2 GetUV(uint bufferId, uint vertexIdx) { - if (bufferId == INVALID_HANDLE) - { - return 0.0f.xx; - } - else - { - return uvBuffer[bufferId][vertexIdx]; - } + return (bufferId == INVALID_HANDLE) ? 0.0f.xx : vertexDataBuffer[bufferId][vertexIdx].m_TexCoord0.xy; } float4 GetPosition(uint bufferId, uint vertexIdx) @@ -32,7 +25,7 @@ float4 GetPosition(uint bufferId, uint vertexIdx) float4 GetColor(uint bufferId, uint vertexIdx) { - return (bufferId != INVALID_HANDLE) ? colorBuffer[bufferId][vertexIdx] : float4(1.0f, 0.0f, 1.0f, 1.0f); + return (bufferId == INVALID_HANDLE) ? float4(1.0f, 0.0f, 1.0f, 1.0f) : vertexDataBuffer[bufferId][vertexIdx].m_Color0; } float4x4 GetModel(uint bufferId, uint index) @@ -44,8 +37,8 @@ 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); + output.outUV = GetUV(pcb.vertexDataHandle, stage_input.vertexIndex); + output.outColor = GetColor(pcb.vertexDataHandle, 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);