| 262 | } |
| 263 | |
| 264 | void RenderGraphCompiler::allocateResources(ref<Device> pDevice, ResourceCache* pResourceCache) |
| 265 | { |
| 266 | // Build list to look up execution order index from the pass |
| 267 | std::unordered_map<RenderPass*, uint32_t> passToIndex; |
| 268 | for (size_t i = 0; i < mExecutionList.size(); i++) |
| 269 | { |
| 270 | passToIndex.emplace(mExecutionList[i].pPass.get(), uint32_t(i)); |
| 271 | } |
| 272 | |
| 273 | for (size_t i = 0; i < mExecutionList.size(); i++) |
| 274 | { |
| 275 | uint32_t nodeIndex = mExecutionList[i].index; |
| 276 | |
| 277 | const DirectedGraph::Node* pNode = mGraph.mpGraph->getNode(nodeIndex); |
| 278 | FALCOR_ASSERT(pNode); |
| 279 | RenderPass* pCurrPass = mGraph.mNodeData[nodeIndex].pPass.get(); |
| 280 | const auto& passReflection = mExecutionList[i].reflector; |
| 281 | |
| 282 | auto isResourceUsed = [&](auto field) |
| 283 | { |
| 284 | if (!is_set(field.getFlags(), RenderPassReflection::Field::Flags::Optional)) |
| 285 | return true; |
| 286 | if (mGraph.isGraphOutput({nodeIndex, field.getName()})) |
| 287 | return true; |
| 288 | for (uint32_t e = 0; e < pNode->getOutgoingEdgeCount(); e++) |
| 289 | { |
| 290 | const auto& edgeData = mGraph.mEdgeData[pNode->getOutgoingEdge(e)]; |
| 291 | if (edgeData.srcField == field.getName()) |
| 292 | return true; |
| 293 | } |
| 294 | return false; |
| 295 | }; |
| 296 | |
| 297 | // Register all pass outputs |
| 298 | for (size_t f = 0; f < passReflection.getFieldCount(); f++) |
| 299 | { |
| 300 | auto field = *passReflection.getField(f); |
| 301 | std::string fullFieldName = mGraph.mNodeData[nodeIndex].name + '.' + field.getName(); |
| 302 | |
| 303 | // Skip input resources, we never allocate them |
| 304 | if (!is_set(field.getVisibility(), RenderPassReflection::Field::Visibility::Input)) |
| 305 | { |
| 306 | if (isResourceUsed(field) == false) |
| 307 | continue; |
| 308 | |
| 309 | // Resource lifetime for graph outputs must extend to end of graph execution |
| 310 | bool graphOutput = mGraph.isGraphOutput({nodeIndex, field.getName()}); |
| 311 | uint32_t lifetime = graphOutput ? uint32_t(-1) : uint32_t(i); |
| 312 | if (graphOutput && field.getBindFlags() != ResourceBindFlags::None) |
| 313 | field.bindFlags(field.getBindFlags() | ResourceBindFlags::ShaderResource); // Adding ShaderResource for graph outputs |
| 314 | pResourceCache->registerField(fullFieldName, field, lifetime); |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | // Go over the pass inputs, add them as aliases to the outputs that connect to them (which should be already registered above) |
| 319 | for (uint32_t e = 0; e < pNode->getIncomingEdgeCount(); e++) |
| 320 | { |
| 321 | uint32_t edgeIndex = pNode->getIncomingEdge(e); |
no test coverage detected