From 2e37306dce0f0c151ba9401d6a5d5e80c36e28cc Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 30 Nov 2020 20:36:47 -0800 Subject: GLTF Loader: implemented buffer suballocation in cache --- AssetLoader/interface/GLTFLoader.hpp | 83 ++++++++++---- AssetLoader/interface/GLTFResourceManager.hpp | 13 ++- AssetLoader/src/GLTFLoader.cpp | 154 +++++++++++++++++--------- 3 files changed, 170 insertions(+), 80 deletions(-) diff --git a/AssetLoader/interface/GLTFLoader.hpp b/AssetLoader/interface/GLTFLoader.hpp index a0c887f..8effc2b 100644 --- a/AssetLoader/interface/GLTFLoader.hpp +++ b/AssetLoader/interface/GLTFLoader.hpp @@ -282,12 +282,15 @@ struct Model float4 weight0; }; - RefCntAutoPtr pVertexBuffer[2]; - RefCntAutoPtr pIndexBuffer; - Uint32 IndexCount = 0; + enum BUFFER_ID + { + BUFFER_ID_VERTEX0 = 0, + BUFFER_ID_VERTEX1, + BUFFER_ID_INDEX, + BUFFER_ID_NUM_BUFFERS + }; - GLTFResourceManager::BufferAllocation VBAllocations[2]; - GLTFResourceManager::BufferAllocation IBAllocation; + Uint32 IndexCount = 0; /// Transformation matrix that transforms unit cube [0,1]x[0,1]x[0,1] into /// axis-aligned bounding box in model space. @@ -298,22 +301,6 @@ struct Model std::vector> Skins; - struct TextureInfo - { - RefCntAutoPtr pTexture; - GLTFResourceManager::TextureAllocation CacheAllocation; - float4 UVScaleBias{1, 1, 0, 0}; - }; - std::vector Textures; - - struct ResourceInitData; - std::unique_ptr InitData; - - ITexture* GetTexture(Uint32 Index) - { - return Textures[Index].pTexture; - } - std::vector> TextureSamplers; std::vector Materials; std::vector Animations; @@ -355,6 +342,41 @@ struct Model void PrepareGPUResources(IDeviceContext* pCtx); + IBuffer* GetBuffer(BUFFER_ID BuffId, Uint32& Offset) + { + VERIFY_EXPR(BuffId < BUFFER_ID_NUM_BUFFERS); + auto& Buff = Buffers[BuffId]; + if (Buff.pBuffer) + { + Offset = 0; + return Buff.pBuffer; + } + else if (CacheInfo.pResourceMgr != nullptr) + { + Offset = static_cast(Buff.CacheAllocation.Region.UnalignedOffset); + return CacheInfo.pResourceMgr->GetBuffer(Buff.CacheAllocation); + } + + Offset = 0; + return nullptr; + } + + ITexture* GetTexture(Uint32 Index) + { + auto& TexInfo = Textures[Index]; + if (TexInfo.pTexture) + return TexInfo.pTexture; + else if (CacheInfo.pResourceMgr) + return CacheInfo.pResourceMgr->GetTexture(TexInfo.CacheAllocation); + else + return nullptr; + } + + const float4& GetUVScaleBias(Uint32 Index) + { + return Textures[Index].UVScaleBias; + } + private: void LoadFromFile(IRenderDevice* pDevice, IDeviceContext* pContext, @@ -384,6 +406,25 @@ private: Node* NodeFromIndex(uint32_t index); GLTFCacheInfo CacheInfo; + + struct ResourceInitData; + std::unique_ptr InitData; + + struct BufferInfo + { + RefCntAutoPtr pBuffer; + + GLTFResourceManager::BufferAllocation CacheAllocation; + }; + std::array Buffers; + + struct TextureInfo + { + RefCntAutoPtr pTexture; + GLTFResourceManager::TextureAllocation CacheAllocation; + float4 UVScaleBias{1, 1, 0, 0}; + }; + std::vector Textures; }; } // namespace GLTF diff --git a/AssetLoader/interface/GLTFResourceManager.hpp b/AssetLoader/interface/GLTFResourceManager.hpp index 520a149..9a8fbbe 100644 --- a/AssetLoader/interface/GLTFResourceManager.hpp +++ b/AssetLoader/interface/GLTFResourceManager.hpp @@ -49,7 +49,8 @@ public: struct BufferAllocation { - Uint32 BufferIndex = 0; + Int32 BufferIndex = -1; + VariableSizeAllocationsManager::Allocation Region; bool IsValid() const @@ -59,7 +60,7 @@ public: }; struct TextureAllocation { - Uint32 TextureIndex = 0; + Int32 TextureIndex = -1; DynamicAtlasManager::Region Region; bool IsValid() const @@ -91,18 +92,18 @@ public: void FreeBufferSpace(BufferAllocation&& Allocation); - IBuffer* GetBuffer(Uint32 Idx) + IBuffer* GetBuffer(const BufferAllocation& Allocation) { - return m_Buffers[Idx].pBuffer; + return m_Buffers[Allocation.BufferIndex].pBuffer; } TextureAllocation AllocateTextureSpace(Uint32 TextureIndex, Uint32 Width, Uint32 Height); void FreeTextureSpace(TextureAllocation&& Allocation); - ITexture* GetTexture(Uint32 Idx) + ITexture* GetTexture(const TextureAllocation& Allocation) { - return m_Textures[Idx].pTexture; + return m_Textures[Allocation.TextureIndex].pTexture; } private: diff --git a/AssetLoader/src/GLTFLoader.cpp b/AssetLoader/src/GLTFLoader.cpp index 13446f5..bfd074d 100644 --- a/AssetLoader/src/GLTFLoader.cpp +++ b/AssetLoader/src/GLTFLoader.cpp @@ -77,7 +77,7 @@ struct Model::ResourceInitData { std::vector Textures; - std::vector IndexBuffer; + std::vector IndexData; std::vector VertexData0; std::vector VertexData1; }; @@ -270,17 +270,18 @@ Model::~Model() { if (CacheInfo.pResourceMgr != nullptr) { - if (VBAllocations[0].Region.IsValid()) - CacheInfo.pResourceMgr->FreeBufferSpace(std::move(VBAllocations[0])); - if (VBAllocations[1].Region.IsValid()) - CacheInfo.pResourceMgr->FreeBufferSpace(std::move(VBAllocations[1])); - if (IBAllocation.Region.IsValid()) - CacheInfo.pResourceMgr->FreeBufferSpace(std::move(IBAllocation)); + for (auto& Buff : Buffers) + { + if (Buff.CacheAllocation.Region.IsValid()) + CacheInfo.pResourceMgr->FreeBufferSpace(std::move(Buff.CacheAllocation)); + } + for (auto& Tex : Textures) { if (Tex.CacheAllocation.IsValid()) CacheInfo.pResourceMgr->FreeTextureSpace(std::move(Tex.CacheAllocation)); } + CacheInfo.pResourceMgr->Release(); } } @@ -339,7 +340,7 @@ void Model::LoadNode(IRenderDevice* pDevice, { const tinygltf::Primitive& primitive = gltf_mesh.primitives[j]; - uint32_t indexStart = static_cast(InitData->IndexBuffer.size()); + uint32_t indexStart = static_cast(InitData->IndexData.size()); uint32_t vertexStart = static_cast(InitData->VertexData0.size()); VERIFY_EXPR(InitData->VertexData1.empty() || InitData->VertexData0.size() == InitData->VertexData1.size()); @@ -507,8 +508,8 @@ void Model::LoadNode(IRenderDevice* pDevice, const void* dataPtr = &(buffer.data[accessor.byteOffset + bufferView.byteOffset]); - auto& IndexBuffer = InitData->IndexBuffer; - IndexBuffer.reserve(IndexBuffer.size() + accessor.count); + auto& IndexData = InitData->IndexData; + IndexData.reserve(IndexData.size() + accessor.count); switch (accessor.componentType) { case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: @@ -516,7 +517,7 @@ void Model::LoadNode(IRenderDevice* pDevice, const uint32_t* buf = static_cast(dataPtr); for (size_t index = 0; index < accessor.count; index++) { - IndexBuffer.push_back(buf[index] + vertexStart); + IndexData.push_back(buf[index] + vertexStart); } break; } @@ -525,7 +526,7 @@ void Model::LoadNode(IRenderDevice* pDevice, const uint16_t* buf = static_cast(dataPtr); for (size_t index = 0; index < accessor.count; index++) { - IndexBuffer.push_back(buf[index] + vertexStart); + IndexData.push_back(buf[index] + vertexStart); } break; } @@ -534,7 +535,7 @@ void Model::LoadNode(IRenderDevice* pDevice, const uint8_t* buf = static_cast(dataPtr); for (size_t index = 0; index < accessor.count; index++) { - IndexBuffer.push_back(buf[index] + vertexStart); + IndexData.push_back(buf[index] + vertexStart); } break; } @@ -760,8 +761,7 @@ void Model::LoadTextures(IRenderDevice* pDevice, TexInfo.CacheAllocation = CacheInfo.pResourceMgr->AllocateTextureSpace(0, gltf_image.width, gltf_image.height); if (TexInfo.CacheAllocation.IsValid()) { - TexInfo.pTexture = CacheInfo.pResourceMgr->GetTexture(0); - const auto& TexDesc = TexInfo.pTexture->GetDesc(); + const auto& TexDesc = CacheInfo.pResourceMgr->GetTexture(TexInfo.CacheAllocation)->GetDesc(); const auto& Region = TexInfo.CacheAllocation.Region; TexInitData = PrepareGLTFTextureInitData(gltf_image, AlphaCutoff, Region.x, Region.y, TexDesc.MipLevels); @@ -849,6 +849,8 @@ void Model::PrepareGPUResources(IDeviceContext* pCtx) if (!InitData) return; + std::vector Barriers; + VERIFY_EXPR(InitData->Textures.size() == Textures.size()); for (Uint32 i = 0; i < Textures.size(); ++i) { @@ -874,6 +876,12 @@ void Model::PrepareGPUResources(IDeviceContext* pCtx) { pCtx->GenerateMips(pTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); } + + if (Textures[i].pTexture != nullptr) + { + VERIFY_EXPR(pTexture == Textures[i].pTexture); + Barriers.emplace_back(StateTransitionDesc{pTexture, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_SHADER_RESOURCE, true}); + } } else if (TexData.pStagingTex) { @@ -884,19 +892,36 @@ void Model::PrepareGPUResources(IDeviceContext* pCtx) UNEXPECTED("Either levels data or staging texture should not be null"); } } - InitData.reset(); - std::vector Barriers; - Barriers.reserve(Textures.size()); - for (auto& TexInfo : Textures) + auto UpdateBuffer = [&](BUFFER_ID BuffId, const void* pData, size_t Size) // { - if (TexInfo.pTexture) + Uint32 Offset = 0; + auto* pBuffer = GetBuffer(BuffId, Offset); + pCtx->UpdateBuffer(pBuffer, Offset, static_cast(Size), pData, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + if (Buffers[BuffId].pBuffer != nullptr) { - StateTransitionDesc Barrier{TexInfo.pTexture, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_SHADER_RESOURCE}; - Barrier.UpdateResourceState = true; - Barriers.emplace_back(Barrier); + VERIFY_EXPR(Buffers[BuffId].pBuffer == pBuffer); + Barriers.emplace_back(StateTransitionDesc{pBuffer, RESOURCE_STATE_UNKNOWN, BuffId == BUFFER_ID_INDEX ? RESOURCE_STATE_INDEX_BUFFER : RESOURCE_STATE_VERTEX_BUFFER, true}); } + }; + + if (!InitData->VertexData0.empty()) + { + const auto& VertexData = InitData->VertexData0; + UpdateBuffer(BUFFER_ID_VERTEX0, VertexData.data(), VertexData.size() * sizeof(VertexData[0])); } + if (!InitData->VertexData1.empty()) + { + const auto& VertexData = InitData->VertexData1; + UpdateBuffer(BUFFER_ID_VERTEX1, VertexData.data(), VertexData.size() * sizeof(VertexData[0])); + } + if (!InitData->IndexData.empty()) + { + const auto& IndexData = InitData->IndexData; + UpdateBuffer(BUFFER_ID_INDEX, IndexData.data(), IndexData.size() * sizeof(IndexData[0])); + } + + InitData.reset(); if (!Barriers.empty()) pCtx->TransitionResourceStates(static_cast(Barriers.size()), Barriers.data()); @@ -1552,50 +1577,73 @@ void Model::LoadFromFile(IRenderDevice* pDevice, { auto& VertexData0 = InitData->VertexData0; - VERIFY_EXPR(!VertexData0.empty()); - BufferDesc VBDesc; - VBDesc.Name = "GLTF vertex attribs 0 buffer"; - VBDesc.uiSizeInBytes = static_cast(VertexData0.size() * sizeof(VertexData0[0])); - VBDesc.BindFlags = BIND_VERTEX_BUFFER; - VBDesc.Usage = USAGE_IMMUTABLE; + auto BufferSize = static_cast(VertexData0.size() * sizeof(VertexData0[0])); + if (CacheInfo.pResourceMgr != nullptr) + { + Buffers[BUFFER_ID_VERTEX0].CacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.VertexBuffer0Idx, BufferSize, 1); + } + else + { - BufferData BuffData(VertexData0.data(), VBDesc.uiSizeInBytes); - pDevice->CreateBuffer(VBDesc, &BuffData, &pVertexBuffer[0]); + VERIFY_EXPR(!VertexData0.empty()); + BufferDesc VBDesc; + VBDesc.Name = "GLTF vertex attribs 0 buffer"; + VBDesc.uiSizeInBytes = BufferSize; + VBDesc.BindFlags = BIND_VERTEX_BUFFER; + VBDesc.Usage = USAGE_IMMUTABLE; - VertexData0.clear(); + BufferData BuffData(VertexData0.data(), VBDesc.uiSizeInBytes); + pDevice->CreateBuffer(VBDesc, &BuffData, &Buffers[BUFFER_ID_VERTEX0].pBuffer); + + VertexData0.clear(); + } } { auto& VertexData1 = InitData->VertexData1; + auto BufferSize = static_cast(VertexData1.size() * sizeof(VertexData1[0])); + if (CacheInfo.pResourceMgr != nullptr) + { + Buffers[BUFFER_ID_VERTEX1].CacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.VertexBuffer1Idx, BufferSize, 1); + } + else + { + VERIFY_EXPR(!VertexData1.empty()); + BufferDesc VBDesc; + VBDesc.Name = "GLTF vertex attribs 1 buffer"; + VBDesc.uiSizeInBytes = BufferSize; + VBDesc.BindFlags = BIND_VERTEX_BUFFER; + VBDesc.Usage = USAGE_IMMUTABLE; - VERIFY_EXPR(!VertexData1.empty()); - BufferDesc VBDesc; - VBDesc.Name = "GLTF vertex attribs 1 buffer"; - VBDesc.uiSizeInBytes = static_cast(VertexData1.size() * sizeof(VertexData1[0])); - VBDesc.BindFlags = BIND_VERTEX_BUFFER; - VBDesc.Usage = USAGE_IMMUTABLE; - - BufferData BuffData(VertexData1.data(), VBDesc.uiSizeInBytes); - pDevice->CreateBuffer(VBDesc, &BuffData, &pVertexBuffer[1]); + BufferData BuffData(VertexData1.data(), VBDesc.uiSizeInBytes); + pDevice->CreateBuffer(VBDesc, &BuffData, &Buffers[BUFFER_ID_VERTEX1].pBuffer); - VertexData1.clear(); + VertexData1.clear(); + } } - if (!InitData->IndexBuffer.empty()) + if (!InitData->IndexData.empty()) { - auto& IndexBuffer = InitData->IndexBuffer; - - BufferDesc IBDesc; - IBDesc.Name = "GLTF inde buffer"; - IBDesc.uiSizeInBytes = static_cast(IndexBuffer.size() * sizeof(IndexBuffer[0])); - IBDesc.BindFlags = BIND_INDEX_BUFFER; - IBDesc.Usage = USAGE_IMMUTABLE; + auto& IndexBuffer = InitData->IndexData; + auto BufferSize = static_cast(IndexBuffer.size() * sizeof(IndexBuffer[0])); + if (CacheInfo.pResourceMgr != nullptr) + { + Buffers[BUFFER_ID_INDEX].CacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.IndexBufferIdx, BufferSize, 1); + } + else + { + BufferDesc IBDesc; + IBDesc.Name = "GLTF inde buffer"; + IBDesc.uiSizeInBytes = BufferSize; + IBDesc.BindFlags = BIND_INDEX_BUFFER; + IBDesc.Usage = USAGE_IMMUTABLE; - BufferData BuffData(IndexBuffer.data(), IBDesc.uiSizeInBytes); - pDevice->CreateBuffer(IBDesc, &BuffData, &pIndexBuffer); + BufferData BuffData(IndexBuffer.data(), IBDesc.uiSizeInBytes); + pDevice->CreateBuffer(IBDesc, &BuffData, &Buffers[BUFFER_ID_INDEX].pBuffer); - IndexBuffer.clear(); + IndexBuffer.clear(); + } } if (pContext != nullptr) -- cgit v1.2.3