1/* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef DEVICE_GPU_RESOURCE_MANAGER_BASE_INL 17#define DEVICE_GPU_RESOURCE_MANAGER_BASE_INL 18 19#include <algorithm> 20#include <cinttypes> 21 22#include <render/namespace.h> 23 24#include "util/log.h" 25 26RENDER_BEGIN_NAMESPACE() 27template<typename ResourceType, typename CreateInfoType> 28inline GpuResourceManagerTyped<ResourceType, CreateInfoType>::GpuResourceManagerTyped(Device& device) : device_(device) 29{} 30 31template<typename ResourceType, typename CreateInfoType> 32inline ResourceType* GpuResourceManagerTyped<ResourceType, CreateInfoType>::Get(const uint32_t index) const 33{ 34 if (index < resources_.size()) { 35 return resources_[index].get(); 36 } else { 37 return nullptr; 38 } 39} 40 41template<typename ResourceType, typename CreateInfoType> 42inline void GpuResourceManagerTyped<ResourceType, CreateInfoType>::Create( 43 const uint32_t index, const CreateInfoType& desc, BASE_NS::unique_ptr<ResourceType> optionalResource) 44{ 45 if (index < static_cast<uint32_t>(resources_.size())) { // use existing location 46 // add old for deallocation if found 47 if (resources_[index]) { 48 pendingDeallocations_.push_back({ move(resources_[index]), device_.GetFrameCount() }); 49 } 50 51 if (optionalResource) { 52 resources_[index] = move(optionalResource); 53 } else { 54 if constexpr (BASE_NS::is_same_v<ResourceType, GpuBuffer>) { 55 resources_[index] = device_.CreateGpuBuffer(desc); 56 } else if constexpr (BASE_NS::is_same_v<ResourceType, GpuImage>) { 57 resources_[index] = device_.CreateGpuImage(desc); 58 } else if constexpr (BASE_NS::is_same_v<ResourceType, GpuSampler>) { 59 resources_[index] = device_.CreateGpuSampler(desc); 60 } else if constexpr (BASE_NS::is_same_v<ResourceType, GpuAccelerationStructure>) { 61 resources_[index] = device_.CreateGpuAccelerationStructure(desc); 62 } 63 } 64 } else { 65 if (optionalResource) { 66 resources_.emplace_back(move(optionalResource)); 67 } else { 68 if constexpr (BASE_NS::is_same_v<ResourceType, GpuBuffer>) { 69 resources_.emplace_back(device_.CreateGpuBuffer(desc)); 70 } else if constexpr (BASE_NS::is_same_v<ResourceType, GpuImage>) { 71 resources_.emplace_back(device_.CreateGpuImage(desc)); 72 } else if constexpr (BASE_NS::is_same_v<ResourceType, GpuSampler>) { 73 resources_.emplace_back(device_.CreateGpuSampler(desc)); 74 } else if constexpr (BASE_NS::is_same_v<ResourceType, GpuAccelerationStructure>) { 75 resources_.emplace_back(device_.CreateGpuAccelerationStructure(desc)); 76 } 77 } 78 PLUGIN_ASSERT(index == static_cast<uint32_t>(resources_.size() - 1u)); 79 } 80} 81 82template<typename ResourceType, typename CreateInfoType> 83inline void GpuResourceManagerTyped<ResourceType, CreateInfoType>::HandlePendingDeallocations() 84{ 85 if (!pendingDeallocations_.empty()) { 86 auto const minAge = device_.GetCommandBufferingCount() + 1; 87 auto const ageLimit = (device_.GetFrameCount() < minAge) ? 0 : (device_.GetFrameCount() - minAge); 88 89 auto const oldResources = std::partition(pendingDeallocations_.begin(), pendingDeallocations_.end(), 90 [ageLimit](auto const& handleTime) { return handleTime.frameIndex >= ageLimit; }); 91 92 pendingDeallocations_.erase(oldResources, pendingDeallocations_.end()); 93 } 94} 95 96template<typename ResourceType, typename CreateInfoType> 97inline void GpuResourceManagerTyped<ResourceType, CreateInfoType>::HandlePendingDeallocationsImmediate() 98{ 99 pendingDeallocations_.clear(); 100} 101 102template<typename ResourceType, typename CreateInfoType> 103inline void GpuResourceManagerTyped<ResourceType, CreateInfoType>::Destroy(const uint32_t index) 104{ 105 PLUGIN_ASSERT(index < static_cast<uint32_t>(resources_.size())); 106 if (index < static_cast<uint32_t>(resources_.size())) { 107 pendingDeallocations_.push_back({ move(resources_[index]), device_.GetFrameCount() }); 108 } 109} 110 111template<typename ResourceType, typename CreateInfoType> 112inline void GpuResourceManagerTyped<ResourceType, CreateInfoType>::DestroyImmediate(const uint32_t index) 113{ 114 PLUGIN_ASSERT(index < static_cast<uint32_t>(resources_.size())); 115 if (index < static_cast<uint32_t>(resources_.size())) { 116 resources_[index].reset(); 117 } 118} 119 120template<typename ResourceType, typename CreateInfoType> 121inline void GpuResourceManagerTyped<ResourceType, CreateInfoType>::Resize(const size_t maxSize) 122{ 123 // ATM our code does not allow reducing the stored space 124 // this assert is here to note the current design 125 PLUGIN_ASSERT(maxSize >= resources_.size()); 126 resources_.resize(maxSize); 127} 128 129#if (RENDER_VALIDATION_ENABLED == 1) 130template<typename ResourceType, typename CreateInfoType> 131size_t GpuResourceManagerTyped<ResourceType, CreateInfoType>::GetValidResourceCount() const 132{ 133 size_t count = 0; 134 for (const auto& res : resources_) { 135 if (res) { 136 count++; 137 } 138 } 139 return count; 140} 141#endif 142RENDER_END_NAMESPACE() 143 144#endif // DEVICE_GPU_RESOURCE_MANAGER_BASE_INL