|
5 | 5 |
|
6 | 6 | namespace nbl::video
|
7 | 7 | {
|
8 |
| - |
9 |
| - |
10 |
| -struct dep_gather_hash |
11 |
| -{ |
12 |
| - template<asset::Asset AssetType> |
13 |
| - inline size_t operator()(const CAssetConverter::root_t<AssetType>& in) const |
14 |
| - { |
15 |
| - return std::hash<const void*>{}(in.asset)^(in.unique ? (~0x0ull):0x0ull); |
16 |
| - } |
17 |
| -}; |
18 |
| -template<asset::Asset AssetType> |
19 |
| -using dep_gather_cache_t = core::unordered_multimap<CAssetConverter::root_t<AssetType>,typename asset_traits<AssetType>::patch_t,dep_gather_hash>; |
| 8 | +using namespace nbl::core; |
| 9 | +using namespace nbl::asset; |
20 | 10 |
|
21 | 11 | auto CAssetConverter::reserve(const SInput& input) -> SResults
|
22 | 12 | {
|
23 | 13 | SResults retval = {};
|
24 |
| - if (input.readCache->m_params.device!=m_params.device) |
| 14 | + if (input.readCache && input.readCache->m_params.device!=m_params.device) |
25 | 15 | return retval;
|
26 | 16 |
|
27 |
| - core::tuple_transform_t<dep_gather_cache_t,supported_asset_types> dep_gather_caches; |
28 |
| - // gather all dependencies (DFS graph search) and patch |
| 17 | + // gather all dependencies (DFS graph search) and patch, this happens top-down |
29 | 18 | // do not deduplicate/merge assets at this stage, only patch GPU creation parameters
|
30 | 19 | {
|
31 |
| - core::stack<const asset::IAsset*> dfsStack; |
32 |
| - auto push = [&]<asset::Asset AssetType>(const CAssetConverter::input_t<AssetType>& in)->void |
| 20 | + core::stack<const IAsset*> dfsStack; |
| 21 | + // returns true if new element was inserted |
| 22 | + auto cache = [&]<Asset AssetType>(const CAssetConverter::SInput::input_t<AssetType>& in)->bool |
33 | 23 | {
|
34 |
| - using cache_t = dep_gather_cache_t<AssetType>; |
35 |
| - auto& cache = std::get<cache_t>(dep_gather_caches); |
36 |
| - auto found = cache.equal_range(in); |
| 24 | + if (!in.key.asset) |
| 25 | + return false; |
| 26 | + |
| 27 | + using cache_t = SResults::dag_cache_t<AssetType>; |
| 28 | + auto& cache = std::get<cache_t>(retval.m_typedDagNodes); |
| 29 | + auto found = cache.equal_range(in.key); |
37 | 30 | if (found.first!=found.second)
|
38 | 31 | {
|
39 | 32 | #if 0
|
40 | 33 | // found the thing, combine patches
|
41 | 34 | const auto& cachedPatch = found->patch;
|
42 | 35 | if (auto combined=in.patch; combined)
|
| 36 | + { |
43 | 37 | const_cast<asset_traits<AssetType>::patch_t&>(cachedPatch) = combined;
|
| 38 | + return false; |
| 39 | + } |
44 | 40 | #endif
|
| 41 | + // check whether the item is creatable after patching, else duplicate/de-alias |
45 | 42 | }
|
46 | 43 | // insert a new entry
|
47 |
| - cache.insert(found.first,{in,{}/*in.patch*/}); |
| 44 | + cache.insert(found.first,{in.key,{.patch=in.patch}}); |
| 45 | + return true; |
48 | 46 | };
|
49 |
| - core::visit([&push]<asset::Asset AssetType>(const SInput::span_t<AssetType> assets)->void{ |
50 |
| - for (auto& asset : assets) |
51 |
| - push(asset); |
| 47 | + // initialize stacks |
| 48 | + core::visit([&]<Asset AssetType>(const SInput::span_t<AssetType> inputs)->void{ |
| 49 | + for (auto& in : inputs) |
| 50 | + if (cache(in) && AssetType::HasDependents) |
| 51 | + dfsStack.push(in.key.asset); |
52 | 52 | },input.assets);
|
53 |
| -/* |
54 |
| - auto pushAll = [&push]()->void |
55 |
| - { |
56 |
| - }; |
| 53 | + // everything that's not explicit has `!unique` and default patch params |
57 | 54 | while (!dfsStack.empty())
|
58 | 55 | {
|
59 | 56 | const auto* asset = dfsStack.top();
|
60 | 57 | dfsStack.pop();
|
61 |
| -
|
62 |
| - auto found = std::get<dep_gather_cache_t<asset::ICPUShader>>(dep_gather_caches).find(asset); |
63 |
| - if (!=end()) |
| 58 | + // everything we popped, has already been cached, now time to go over dependents |
| 59 | + switch (asset->getAssetType()) |
64 | 60 | {
|
| 61 | +#if 0 |
| 62 | + case ICPUPipelineLayout::AssetType: |
| 63 | + { |
| 64 | + auto pplnLayout = static_cast<const ICPUPipelineLayout*>(asset); |
| 65 | + for (auto i=0; i<ICPUPipelineLayout::DESCRIPTOR_SET_COUNT; i++) |
| 66 | + if (auto layout=pplnLayout->getDescriptorSetLayout(i); layout) |
| 67 | + if (cache({/*TODO*/})) |
| 68 | + dfsStack.push(layout); |
| 69 | + break; |
| 70 | + } |
| 71 | + case ICPUDescriptorSetLayout::AssetType: |
| 72 | + { |
| 73 | + auto layout = static_cast<const ICPUDescriptorSetLayout*>(asset); |
| 74 | + for (const auto& sampler : layout->getImmutableSamplers()) |
| 75 | + cache({/*TODO*/}); |
| 76 | + break; |
| 77 | + } |
| 78 | +#endif |
| 79 | + case ICPUDescriptorSet::AssetType: |
| 80 | + { |
| 81 | + _NBL_TODO(); |
| 82 | + break; |
| 83 | + } |
| 84 | + case ICPUImageView::AssetType: |
| 85 | + { |
| 86 | + _NBL_TODO(); |
| 87 | + break; |
| 88 | + } |
| 89 | + case ICPUBufferView::AssetType: |
| 90 | + { |
| 91 | + _NBL_TODO(); |
| 92 | + break; |
| 93 | + } |
| 94 | + // these assets have no dependants, should have never been pushed on the stack |
| 95 | + default: |
| 96 | + assert(false); |
| 97 | + break; |
65 | 98 | }
|
66 | 99 | }
|
67 |
| -*/ |
68 | 100 | }
|
| 101 | + // now we have a set of implicit gpu creation parameters we want to create resources with |
| 102 | + // and a mapping from (Asset,Patch) -> UniqueAsset |
69 | 103 |
|
70 |
| - // check whether the item is creatable after patching, else duplicate/de-alias |
71 |
| - |
72 |
| - // now we have a list of gpu creation parameters we want to create resources with |
73 |
| - |
74 |
| -#if 0 |
75 |
| - auto stuff = [&]<typename AssetType>(const input_t<AssetType>& key)->void |
| 104 | + auto dedup = [&]<Asset AssetType>()->void |
76 | 105 | {
|
77 |
| - // |
78 |
| - CCache::search_t<AssetType> s = key; |
79 |
| - if (!s.patch.has_value()) |
80 |
| - s.patch = asset_traits<AssetType>::defaultPatch(key.asset); |
81 |
| - const size_t hash = CCache::Hash{}(s); |
82 |
| - |
83 |
| - // search by the {asset+patch} in read cache |
84 |
| - if (auto found=input.readCache->find(s,hash); found!=input.readCache->end<AssetType>()) |
| 106 | + using cache_t = SResults::dag_cache_t<AssetType>; |
| 107 | + core::unordered_set<typename cache_t::value_type*/*TODO: Hash,Equals*/> conser; |
| 108 | + for (auto& asset : std::get<cache_t>(retval.m_typedDagNodes)) |
85 | 109 | {
|
86 |
| - // |
| 110 | + auto [it, inserted] = conser.insert(&asset); |
| 111 | + if (inserted) |
| 112 | + { |
| 113 | + if (input.readCache) |
| 114 | + continue; // TODO: below |
| 115 | +// if (auto found=input.readCache->find(); found!=input.readCache->end()) |
| 116 | +// asset.second.result = found->result; |
| 117 | + } |
| 118 | + else |
| 119 | + { |
| 120 | + assert(!asset.second.canonical); |
| 121 | + asset.second.canonical = &(*it)->second; |
| 122 | + } |
87 | 123 | }
|
88 |
| - |
89 |
| - // reserve in write cache |
90 | 124 | };
|
91 |
| -#endif |
92 |
| - |
93 |
| - // if read cache |
94 |
| - // find deps in read cache |
95 |
| - // mark deps as ready/found |
96 |
| - // if not ready/found |
97 |
| - // find dep in transient cache |
98 |
| - // if not found, insert and recurse |
99 |
| - |
100 |
| - // see what can be patched/combined |
| 125 | + // Lets see if we can collapse any of the (Asset Content) into the same thing, |
| 126 | + // to correctly de-dup we need to go bottom-up!!! |
| 127 | + dedup.operator()<ICPUShader>(); |
| 128 | +// Shader, DSLayout, PipelineLayout, Compute Pipeline |
| 129 | +// Renderpass, Graphics Pipeline |
| 130 | +// Buffer, BufferView, Sampler, Image, Image View, Bottom Level AS, Top Level AS, Descriptor Set, Framebuffer |
| 131 | +// Buffer -> SRange, patched usage, owner(s) |
| 132 | +// BufferView -> SRange, promoted format |
| 133 | +// Sampler -> Clamped Params (only aniso, really) |
| 134 | +// Image -> this, patched usage, promoted format |
| 135 | +// Image View -> ref to patched Image, patched usage, promoted format |
| 136 | +// Descriptor Set -> unique layout, |
101 | 137 |
|
102 | 138 | return retval;
|
103 | 139 | }
|
@@ -140,9 +176,13 @@ bool CAssetConverter::convert(SResults& reservations, SConvertParams& params)
|
140 | 176 | .writeCache = m_params.compilerCache.get()
|
141 | 177 | };
|
142 | 178 |
|
| 179 | + for (auto& shader : std::get<SResults::dag_cache_t<ICPUShader>>(reservations.m_typedDagNodes)) |
| 180 | + if (!shader.second.canonical) |
143 | 181 | {
|
144 |
| - params.cpushader = nullptr; // TODO |
145 |
| - reservations.get<asset::ICPUShader>().emplace_back(device->createShader(params)); |
| 182 | + assert(!shader.second.result); |
| 183 | + // custom code start |
| 184 | + params.cpushader = shader.first.asset; |
| 185 | + shader.second.result = device->createShader(params); |
146 | 186 | }
|
147 | 187 | }
|
148 | 188 |
|
|
0 commit comments