| 136 | } |
| 137 | |
| 138 | VulkanMemoryManager::AllocationPtr VulkanMemoryManager::Allocate(ResourceType resourceType, |
| 139 | VkMemoryRequirements memReqs, uint64_t blockHash) |
| 140 | { |
| 141 | size_t const intResType = static_cast<size_t>(resourceType); |
| 142 | auto const alignedSize = GetAligned(static_cast<uint32_t>(memReqs.size), GetSizeAlignment(memReqs)); |
| 143 | // Looking for an existed block. |
| 144 | { |
| 145 | auto & m = m_memory[intResType]; |
| 146 | auto const it = m.find(blockHash); |
| 147 | if (it != m.end()) |
| 148 | { |
| 149 | CHECK(!it->second.empty(), ()); |
| 150 | auto & block = it->second.back(); |
| 151 | auto const alignedOffset = GetAligned(block->m_freeOffset, GetOffsetAlignment(resourceType)); |
| 152 | |
| 153 | // There is space in the current block. |
| 154 | if (!block->m_isBlocked && (block->m_blockSize >= alignedOffset + alignedSize)) |
| 155 | { |
| 156 | block->m_freeOffset = alignedOffset + alignedSize; |
| 157 | block->m_allocationCounter++; |
| 158 | return std::make_shared<Allocation>(resourceType, blockHash, alignedOffset, alignedSize, make_ref(block)); |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | // Looking for a block in free ones. |
| 163 | auto & fm = m_freeBlocks[intResType]; |
| 164 | // Free blocks array must be sorted by size. |
| 165 | auto const freeBlockIt = std::lower_bound(fm.begin(), fm.end(), alignedSize, LessBlockSize()); |
| 166 | if (freeBlockIt != fm.end()) |
| 167 | { |
| 168 | drape_ptr<MemoryBlock> freeBlock = std::move(*freeBlockIt); |
| 169 | CHECK_EQUAL(freeBlock->m_allocationCounter, 0, ()); |
| 170 | CHECK_EQUAL(freeBlock->m_freeOffset, 0, ()); |
| 171 | CHECK_LESS_OR_EQUAL(alignedSize, freeBlock->m_blockSize, ()); |
| 172 | CHECK(!freeBlock->m_isBlocked, ()); |
| 173 | fm.erase(freeBlockIt); |
| 174 | |
| 175 | freeBlock->m_freeOffset = alignedSize; |
| 176 | freeBlock->m_allocationCounter++; |
| 177 | auto p = std::make_shared<Allocation>(resourceType, blockHash, 0, alignedSize, make_ref(freeBlock)); |
| 178 | |
| 179 | m[blockHash].push_back(std::move(freeBlock)); |
| 180 | return p; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | // Looking for memory index by memory properties. |
| 185 | std::optional<VkMemoryPropertyFlags> fallbackFlags; |
| 186 | auto flags = GetMemoryPropertyFlags(resourceType, fallbackFlags); |
| 187 | auto memoryTypeIndex = GetMemoryTypeIndex(memReqs.memoryTypeBits, flags); |
| 188 | if (!memoryTypeIndex && fallbackFlags) |
| 189 | { |
| 190 | flags = *fallbackFlags; |
| 191 | memoryTypeIndex = GetMemoryTypeIndex(memReqs.memoryTypeBits, flags); |
| 192 | } |
| 193 | |
| 194 | CHECK(memoryTypeIndex, ("Unsupported memory allocation configuration.")); |
| 195 | |